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 });