1

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.

3
  • 1
    But.. Generics are a compile time thing, not a runtime thing.. Commented Dec 24, 2021 at 8:44
  • 1
    You say you want that as an Expression<Action<T>>, so I'd expect the expression you want to build takes a parameter of type T and returns void. That is clearly not the case with the Call(...) expression you have shown. Where is the parameter of type T? Commented Dec 24, 2021 at 8:47
  • @CaiusJard Yes, the method is generic. But I need to call it at runtime. @Sweeper The sig for the method I need to call is void Call<T>(Expression<Action<T>> methodCall); Just providing it a method on T that it should call. But I need to be able to do this at runtime given a request so I'm using MakeGenericMethod(...) with the type I get since I have the MethodInfo but I'm just not sure how to build that Expression<Action<T>> to pass in. I have the example where I can do it as just Action, but I need it to call that on the first parameter that will be provided in the Action<T>. Commented Dec 25, 2021 at 15:45

1 Answer 1

1

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 });
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.