Example:
For reasons outside the scope of this example, I am forced to use this:
UserRepository repository = new UserRepository();
User user = (User)InvokeMethod(repository, "GetUserById", new object[]{2});
private object InvokeMethod(object source, string methodName, object[] parameters)
{
Type sourceType = source.GetType();
MethodInfo methodInfo = sourceType.GetMethod(methodName);
return methodInfo.Invoke(source, parameters);
}
However, I would much prefer something like this:
UserRepository repository = new UserRepository();
User user = GetUserById<User, UserRepository>(repository, m => m.GetUserById(2));
A wrapper could accomplish this. I started to build one, but got stuck. This is what I have:
public TUser GetUserById<TUser, TUserRepository>(TUserRepository repository, Expression<Func<TUserRepository, TUser>> repositoryFunc)
where TUser : User
where TUserRepoistory : UserRepository
{
// How do I use the Expression to setup the next two statements?
string methodName = ""; // should be "GetUserId"
object[] params = null; // should be "object[] { 2 }"
TUser user = (TUser)InvokeMethod(repository, methodName, parameters);
}
Keep in mind I am forced to use the InvokeMethod method. I cannot simply invoke the Func.
This gets complex depending on whether the arguments are literals, captured variables, etc – and whether they are
ref,out, etc. You might want to look at the implementation in protobuf-net.Extensions, here, which has code to all of this – in particular theResolveMethodmethod.The
MethodInfois simple – just castBodytoMethodCallExpressionand obtain the.Method.Name– but for the parameters it recursively calls intoEvaluate– this allows expressions likeSomeMethod(123, x, y.Foo.Bar)to work, where123is a literal,xis a captured variable, andy.Foo.Baris something hanging off a captured variable.