How to dynamically create a method from a string for a lambda expression

My ultimate goal is to create a function that will dynamically pass method names to classes in the Hangfire library.

For example, non-dynamic code works here:

RecurringJob.AddOrUpdate(() => myFunction(), Cron.Hourly)

      

The type of the first argument for AddOrUpdate is Expression<Action>

. My first step was to use reflection to dynamically insert the function name:

Type thisControllerType = this.GetType();
MethodInfo method = thisControllerType.GetMethod(methodName); //methodName passed as string parameter
RecurringJob.AddOrUpdate(() => method.Invoke(this, null), Cron.Hourly);

      

When I check the Hangfire dashboard it seems that this expression evaluates to MethodBase.Invoke

. So I need help passing in the method name dynamically.

This may be enough information to answer my question, but the other path I've taken is trying to generate the entire expression for the argument.

RecurringJob.AddOrUpdate(CreateCallExpression(method), Cron.Hourly);

public Expression<Action> CreateCallExpression(MethodInfo method)
    {
        //trying to pass in zero argument parameter, not sure if this syntax is correct    
        var parameter = System.Linq.Expressions.Expression.Parameter(typeof (Array));
        return System.Linq.Expressions.Expression.Lambda<Action>(System.Linq.Expressions.Expression.Call(method, parameter));
    }

      

In this case, I get the exception {"A static method requires a null instance, a non-static method requires a non-empty instance. \ R \ nParameter name: method"}. I am working on this, but not sure if this is the road I should be going. I've been working on this all day, so I was hoping someone could help me speed up my learning.

+3


source to share


1 answer


The second instance will work by creating a pointer to the method you specified, but to solve your static problem, you just need to change the following line in one of two ways. First you can fill in the static link by declaring the method you will become static and change this line of code:

System.Linq.Expressions.Expression.Call(method, parameter);

      

You will need to provide a null parameter for the invocation method because if you are looking for a static method then the compiler knows exactly what method signature you want, because there will only be 1. The line of code will be updated to:

System.Linq.Expressions.Expression.Call(null, method, parameter); 

      



The second approach is to define a class or "instance" that correlates with a method so that the compiler knows which class to look for to sign the method. You will need to change your code like this:

var myInstance = Expression.Parameter(typeof(MyClass), "inst");
System.Linq.Expressions.Expression.Call(myInstance, method, parameter)

      

I recommend looking at the documentation for Call so you know exactly how the pointer is created.

+2


source







All Articles