如何使用强类型reflection为generics类的方法找到MethodInfo?
我想从具有仅在运行时知道的类型参数的generics类中获取方法的MethodInfo
。
以下是从非generics类获取generics方法的MethodInfo
的方法:
class MyClass { public void MyMethod (T arg) { } } static MethodInfo Resolve (Type type) { Expression<Action> lambda = (c, a) => c.MyMethod (a); MethodCallExpression call = lambda.Body as MethodCallExpression; return call .Method // Get MethodInfo for MyClass.MyMethod .GetGenericMethodDefinition () // Get MethodInfo for MyClass.MyMethod .MakeGenericMethod (type); // Get MethodInfo for MyClass.MyMethod } Resolve (typeof (int)).Invoke (new MyClass (), new object[] {3});
现在,如果我想尝试类似于generics类:
class MyClass { public void MyMethod (T arg) { } } static MethodInfo Resolve (Type type) { Expression<Action<MyClass, object>> lambda = (c, a) => c.MyMethod (a); MethodCallExpression call = lambda.Body as MethodCallExpression; return call .Method // Get MethodInfo for MyClass.MyMethod .SomeMagicMethod (); // FIXME: how can I get a MethodInfo // for MyClass.MyMethod where typeof (T) == type? } Resolve (typeof (string)).Invoke (new MyClass (), new object[] {"Hello, World!"});
可能吗?
public class MyClass { public void MyMethod(T arg, bool flag) { Console.WriteLine("type: MyClass<{0}>, arg: {1}, flag:{2}", typeof(T), arg.ToString(), flag); } public void MyMethod(T arg) { Console.WriteLine("type: MyClass<{0}>, arg: {1}", typeof(T), arg.ToString()); } } public class GenericInvokeTest { static MethodInfo Resolve(Type type) { var name = ActionName
要使其强类型,您应该简化并使用不同的方法:
1)使用表达式获取动作/方法的name
…
var name = ActionName
2)然后做不可避免的reflection部分
var genericType = typeof(MyClass<>).MakeGenericType(new[] { type }); MethodInfo genericTypeMyMethodInfo = genericType.GetMethod(name); // "MyMethod");
ActionName
采用类似方法的地方,例如OnPropertyChanged(x => x.Property)
public static string ActionName(Expression, Action >> expression) { return GetMemberName(expression.Body); } public static string GetMemberName(Expression expression) { switch (expression.NodeType) { case ExpressionType.Lambda: var lambdaExpression = (LambdaExpression)expression; return GetMemberName(lambdaExpression.Body); case ExpressionType.MemberAccess: var memberExpression = (MemberExpression)expression; var supername = GetMemberName(memberExpression.Expression); if (String.IsNullOrEmpty(supername)) return memberExpression.Member.Name; return String.Concat(supername, '.', memberExpression.Member.Name); case ExpressionType.Call: var callExpression = (MethodCallExpression)expression; return callExpression.Method.Name; case ExpressionType.Convert: var unaryExpression = (UnaryExpression)expression; return GetMemberName(unaryExpression.Operand); case ExpressionType.Parameter: return String.Empty; default: throw new ArgumentException( "The expression is not a member access or method call expression"); } }
工作方案:
static MethodInfo Resolve (Type type) { Expression, object>> lambda = (c, a) => c.MyMethod (a); MethodCallExpression call = lambda.Body as MethodCallExpression; MethodInfo[] methods; Type target; target = call .Method // Get MethodInfo for MyClass