示例:
由于本例范围之外的原因,我不得不使用它:
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);
}
但是,我更喜欢这样的事情:
UserRepository repository = new UserRepository();
User user = GetUserById<User, UserRepository>(repository, m => m.GetUserById(2));
包装器可以实现这一点。我开始建立一个,但卡住了。这就是我所拥有的:
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);
}
请记住,我被迫使用InvokeMethod方法。我不能简单地调用Func。
答案 0 :(得分:4)
这会变得复杂,具体取决于参数是文字,捕获的变量等 - 以及它们是ref
,out
等。您可能希望查看protobuf-net中的实现。扩展程序here,其中包含所有这些内容的代码 - 特别是ResolveMethod
方法。
MethodInfo
很简单 - 只需将Body
转换为MethodCallExpression
并获取.Method.Name
- 但对于参数,它会递归调用Evaluate
- 这允许像SomeMethod(123, x, y.Foo.Bar)
这样的表达式可以使用,其中123
是文字,x
是捕获的变量,y.Foo.Bar
是 off 捕获的变量