Home > Enterprise >  Creating a generic lambda expression that includes parameter
Creating a generic lambda expression that includes parameter

Time:12-28

In short I'm trying to build the equivalent of

Call<UnknownRegisteredClass>(r => r.UnknownMethod(...args))

as an Expression<Action<T> via reflection at runtime.

The whole concept of Expressions is quite new to me, but everything I'm finding in the docs doesn't seem to tackle it from a generic/reflection perspective but just from a more of a building expressions with known types.

So far I have managed to rig up the inside expression r.UnknownMethod(...args):

Expression.Lambda<Action>(Expression.Call(Expression.New(actionType), actionMethod, parameterExpressions))

But I'm not sure how to wrap that in another level where that is call is actually made against the parameter of an Action<T>

Seems like it would go something like:

ParameterExpression instance = Expression.Parameter(typeof(T), "instance");
return Expression.Lambda<Action<T>>(Expression.Call(instance, HowDoIGetMyAboveExpressionHere), new ParameterExpression[] { instance });

But that doesn't really work because I can't use <T> since I don't know the type until runtime. If anyone can see what I'm trying to do and has any examples they could point me to I would really appreciate it.

CodePudding user response:

I was apparently pretty close with what I had at the end of my question. I created a local generic method that will return the expression for me and then I just call that at runtime:

public Expression<Action<T>> GetActionExpression<T>(Type type, MethodInfo callingMethod, List<Expression> parameterExpressions)
{
    var callLambdaParameter = Expression.Parameter(type, "p");
    var callBody = Expression.Call(callLambdaParameter, callingMethod, parameterExpressions.ToArray());
    return Expression.Lambda<Action<T>>(callBody, callLambdaParameter);
}

And then call it with:

var genericActionExpression = GetType().GetMethod(nameof(GetActionExpression)).MakeGenericMethod(actionType).Invoke(this, new object[] { actionType, actionMethod, parameterExpressions});

Then I can use what is now basically r => r.UnknownMethod(...args) to call the desired method:

callMethod.Invoke(this, new[] { Caller, genericActionExpression });
  • Related