jeudi 17 septembre 2020

C# extract lambda expression dynamic as string [duplicate]

I have this function:

private string getPropertyAsString<T>(Expression<Func<T, dynamic>> property)
{
}

I want to extract the property from the lambda as string

For example getPropertyAsString<someClass>(x=>x.Test);
Will return "Test"





Get the reflect.Kind of a type which is based on a primitive type

I would like to get the reflect.Kind as a reflect.Interface for a type which implements an interface but where its implementation is based on a primitive type: type id string

An alternative answer for this could be how to get any kind of reflect.Type that returns reflect.Interfaces when calling Kind().

Here is a full example on the Go Playground:

type ID interface {
    myid()
}

type id string

func (id) myid() {}

func main() {
    id := ID(id("test"))
    
    fmt.Println(id)
    fmt.Println(reflect.TypeOf(id))
    
    // How to get the kind to return "reflect.Interface" from the var "id"?
    fmt.Println(reflect.TypeOf(id).Kind())
}




Inspect in python (Migration from Java to Python)

I m working on a java project where I'm using :

myMethodObj = MyClass.class.getMethod(methodName, methodParameter);

(myMethodObj is of type Method (Java reflection API))

I'm using java reflection API here, I want to write this code in python. What will be the way ?

I have tried using inspect.getmembers and MyClass.__dir__ . But Its not working.

Aim is to get the method name (declared inside MyClass) and the parameter list of the method(in Array)

Please help!!





mercredi 16 septembre 2020

Scala accessing members of runtime types using reflection of a class that extends a trait

Suppose I have a MyItem trait and its companion object has an apply() function that creates a class instance called SubItem that extends from MyItem:

import scala.reflect.runtime.{universe => ru}

trait MyItem {
  import MyItem._
  def num: Option[Int]
}

object MyItem {
  class SubItem(val num: Option[Int]) extends MyItem 

  def apply(num: Option[Int]): MyItem = new SubItem(num) // creates SubItem
}

def getTypeTag[T: ru.TypeTag](obj: T) = ru.typeTag[T]

val modifiedItem = MyItem(Some(11))
val theType = getTypeTag(modifiedItem).tpe

If you print out theType above, it will be MyItem.

At this point if you try to use reflection to modify the field num, it's not going to work because MyItem has num as a method, not a field (as in MyItem.SubItem):

val m = ru.runtimeMirror(modifiedItem.getClass.getClassLoader)
val numTermSymb = theType.decl(ru.TermName("num")).asTerm
val im = m.reflect(modifiedItem)
val numFieldMirror = im.reflectField(numTermSymb)  // not going to work
numFieldMirror.get
numFieldMirror.set(Some(999))  // my goal, if possible

Unfortunately, above will throw out scala.ScalaReflectionException: expected a field or an accessor method symbol, you provided method num.

Instead you should do the following:

val numTermSymb = theType.decl(ru.TermName("num")).asMethod
val im = m.reflect(modifiedItem)
val numFieldMirror = im.reflectMethod(numTermSymb)
numFieldMirror() // returns `Some(11)`

But my goal is to access the SubItem class that extends MyItem and modify its field. How can I get an instance of the type MyItem and modify the field in MyItem.SubItem that MyItem's method num is accessing?





How to use method with generics and inheritance?

Having the following classes:

public interface Step<C extends Config> {
  void setConfig(C config);
  void run(Context ctx);
}

and

public class ValidationStep implements Step<ValidationConf> {
  public void setConfig(ValidationConf conf) {}
  // implementation
}

and

public class ProcessStep implements Step<ProcessConf> {
  public void setConfig(ProcessConf conf) {}
  // implementation
}

and

public interface Config {
  Class<? extends Step> type();
}

and

public class ValidationConf implements Config {
  public Class<? extends Step> type() {
    return ValidationStep.class;
  }
}

and

public class ProcessConf implements Config {
  public Class<? extends Step> type() {
    return ProcessStep.class;
  }
}

so, the application needs to dinamically instantiate Step subclasses objects, set the configuration accordingly and run the step, like this.

List<Config> configs = loadConfigsFromRepository(); // contain all subtypes of Config
for (Config conf: configs) {
  Step<? extends Config> step = conf.type().getDeclaredConstructor().newInstance();

  step.setConfig(conf); // compiler complains

  step.run(context);
}

Error message:

"The method setConfig(capture#8-of ? extends Config) in the type Step<capture#8-of ? extends Config> is not applicable for the arguments (Config)".

Checking the documentation, looks like Java won´t be friendly in this case: https://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html

What are the possible solutions to overcome this code restriction step.setConfig(conf);?





Some questions about invoking arbitrary method [closed]

package methods;
import java.lang.reflect.*;
public class MethodTableTest {
    public static void main(String[] args) throws Exception
    {
        Method square = MethodTableTest.class.getMethod("square", double.class);
        Method sqrt = Math.class.getMethod("sqrt", double.class);
        xsave(1, 10, 10, square);  
        xsave(1, 10, 10, sqrt);
    }
    public static double square(double x)
    {
        return x * x;
    }
    
    public static void xsave(double from, double to, int n, Method f)
    {
        // to print out the method as table header
        System.out.println(f);
        double dx = (to - from) / (n - 1);  
        for (double x = from; x <= to; x += dx)
        {
            try
            {
                double y = (Double) f.invoke(null, x);
                System.out.printf("%10.4f | %10.4f%n", x, y);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

Questions:

  1. I do not understand why they set double dx = (to - from) / (n - 1);. What does this mean?

  2. They have the for (double x = from; x <= to; x += dx). I do not understand this for loop so much.

  3. The try/catch, they made the double y = (Double) f.invoke(null, x);. What does this mean? When I use google to find out the meaning of this, they said to me that it "invokes the underlying method represented by this Method object". So in this case, what does this mean?





mardi 15 septembre 2020

Blazor: Generate and bind input controls via reflection

I am new to Blazor/ASP.NET Core and wanted to generate a small formula based on a class with properties via reflection, so I only have to change the code in 1 place if I want to add/remove/change a property. For bool properties it should generate a HTML checkbox input, for int a number and for string a text input, which do validation.

The base code:

using System.ComponentModel.DataAnnotations;

public class Example1
{
    [Required]
    public bool SomeBoolean { get; set; }

    [Required]
    [Range(0, 100, ErrorMessage = "Invalid percentage, must be between 0 and 100.")]
    public int SomePercentage { get; set; }

    [Required]
    [StringLength(200, ErrorMessage = "File Name too long (200 character limit).")]
    public string FileName { get; set; }
}
@using System;
@using System.Reflection;

@code {
    [Parameter]
    public Example1 Ex1 { get; set; } = new Data.Example1();

    [Parameter]
    public bool ReadOnly { get; set; }

    private void HandleValidSubmit()
    {
        Console.WriteLine("The example data is valid.");
    }
}

<EditForm Model="@Ex1" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <table>
        @foreach (var property in typeof(Example1).GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            <tr>
                <td>@property.Name:</td>
                <td>
                    @if (ReadOnly) {
                        @property.GetValue(Ex1)
                    } else {
                        // TODO: Generate input control here.
                    }
                </td>
            </tr>
        }
    </table>
</EditForm>

My current attempt to get it working is the following: I copied what is generated into the .g.cs code file, when directly referencing a property, instead of using reflection, in either an <input/InputCheckbox/InputNumber/InputText> control and replaced the property access with the direct call to the getter or setter that is available via reflection.

@if (ReadOnly) {
    @property.GetValue(Ex1)
} else {
    <InputControl Parent="@this" Object="@Ex1" Property="@property" />
}
public class InputControl : ComponentBase
{
    [Parameter]
    public object Parent { get; set; }
    [Parameter]
    public object Object { get; set; }
    [Parameter]
    public PropertyInfo Property { get; set; }

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        base.BuildRenderTree(builder);

        if (Parent == null || Object == null || Property == null) throw new ArgumentNullException();

        var i = 0;

        // builder.OpenElement(i++, "input");

        switch (Property.PropertyType.FullName)
        {
            case "System.Boolean":
                builder.OpenComponent<InputCheckbox>(i++);
                builder.AddAttribute(i++, "Value", (bool)Property.GetValue(Object));
                builder.AddAttribute(i++, "ValueChanged", EventCallback.Factory.Create(Parent, RuntimeHelpers.CreateInferredEventCallback(this, v => Property.SetValue(Object, v), (bool)Property.GetValue(Object))));
                builder.AddAttribute(i++, "ValueExpression", (Expression<global::System.Func<bool>>)(() => (bool)Property.GetValue(Object)));
                /*
                builder.AddAttribute(i++, "type", "checkbox");
                builder.AddAttribute(i++, "checked", BindConverter.FormatValue((bool)Property.GetValue(Object)));
                builder.AddAttribute(i++, "onchange", EventCallback.Factory.CreateBinder(Parent, v => Property.SetValue(Object, v), (bool)Property.GetValue(Object)));
                builder.SetUpdatesAttributeName("checked");
                */
                break;

            case "System.Int32":
                builder.OpenComponent<InputNumber<int>>(i++);
                builder.AddAttribute(i++, "Value", (int)Property.GetValue(Object));
                builder.AddAttribute(i++, "ValueChanged", EventCallback.Factory.Create(Parent, RuntimeHelpers.CreateInferredEventCallback(this, v => Property.SetValue(Object, v), (int)Property.GetValue(Object))));
                builder.AddAttribute(i++, "ValueExpression", (Expression<global::System.Func<int>>)(() => (int)Property.GetValue(Object)));
                /*
                builder.AddAttribute(i++, "type", "number");
                builder.AddAttribute(i++, "value", BindConverter.FormatValue((int)Property.GetValue(Object)));
                builder.AddAttribute(i++, "onchange", EventCallback.Factory.CreateBinder(Parent, v => Property.SetValue(Object, v), (int)Property.GetValue(Object)));
                builder.SetUpdatesAttributeName("value");
                */
                break;

            case "System.String":
                builder.OpenComponent<InputText>(i++);
                builder.AddAttribute(i++, "Value", (string)Property.GetValue(Object));
                builder.AddAttribute(i++, "ValueChanged", EventCallback.Factory.Create(Parent, RuntimeHelpers.CreateInferredEventCallback(this, v => Property.SetValue(Object, v), (string)Property.GetValue(Object))));
                builder.AddAttribute(i++, "ValueExpression", (Expression<global::System.Func<string>>)(() => (string)Property.GetValue(Object)));
                /*
                builder.AddAttribute(i++, "type", "text");
                builder.AddAttribute(i++, "value", BindConverter.FormatValue((string)Property.GetValue(Object)));
                builder.AddAttribute(i++, "onchange", EventCallback.Factory.CreateBinder(Parent, v => Property.SetValue(Object, v), (string)Property.GetValue(Object)));
                builder.SetUpdatesAttributeName("value");
                */
                break;

            default:
                throw new NotImplementedException($"Unimplemented type `{Property.PropertyType.FullName}` in {nameof(InputControl)}.{nameof(BuildRenderTree)}!");
        }

        // builder.CloseElement();
        builder.CloseComponent();
    }
}

This throws an exception for what I think is created through AddAttribute("ValueExpression"): ArgumentException: The provided expression contains a UnaryExpression which is not supported. FieldIdentifier only supports simple member accessors (fields, properties) of an object.

Using the commented out code instead works for displaying and updating the values without an exception, but no validation for the input fields is happening.

I think this question is somewhat related to How to generate dynamically blazor's @bind-Value? but I would like to use standard controls. How to proceed?