pangular
pangular

Reputation: 709

Expression Tree of a Generic Action

I need to build an expression tree out of Action<T> (if I may formulate it this way) but the problem is that the type T is determined at runtime via reflection.

I need to pass this expression as an argument to a generic method that gets called using the MethodInfo.Invoke API. The type argument for this method and the lambda mentioned above should match.

Is this achievable? Or maybe there are some better / easier ways of doing this?

Here's what the method looks like:

static GenericMethod<T>(Expression<Action<T>> doSomething) {  }

and all I need is to call it, e.g.

Class.GenericMethod<string>(s => { Console.Write(s.GetType()); }

but I need to do this dynamically at runtime.

Upvotes: 1

Views: 77

Answers (1)

svick
svick

Reputation: 244777

It seems you already know how to get and invoke the generic method GenericMethod:

var genericMethod = someType.GetMethod(nameof(GenericMethod), BindingFlags.NonPublic | BindingFlags.Static);
genericMethod.MakeGenericMethod(type).Invoke(null, …);

And you probably also already know how you could create a method that creates the expression you need based on a compile-time T:

static Expression<Action<T>> CreateWriteTypeExpression<T>() =>
    s => Console.Write(s.GetType());

So, how to invoke this CreateWriteTypeExpression based on runtime Type? The same as above for GenericMethod, using reflection.

Put together it would be:

static Expression<Action<T>> CreateWriteTypeExpression<T>() =>
    s => Console.Write(s.GetType());

void CallGenericMethod(MethodInfo genericMethod, Type type)
{
    var writeTypeExpressionMethod = this.GetType()
        .GetMethod(nameof(CreateWriteTypeExpression), BindingFlags.NonPublic | BindingFlags.Static)
        .MakeGenericMethod(type);

    var writeTypeExpression = writeTypeExpressionMethod.Invoke(null, null);

    genericMethod.MakeGenericMethod(type).Invoke(null, new[] { writeTypeExpression });
}

Upvotes: 2

Related Questions