如何使用强类型反射为泛型类的方法查找 MethodInfo? [英] How to find MethodInfo for a method of a generic class using strongly-typed reflection?

查看:39
本文介绍了如何使用强类型反射为泛型类的方法查找 MethodInfo?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从具有仅在运行时已知的类型参数的泛型类中获取方法的 MethodInfo.

I'd like to get a MethodInfo of a method from a generic class having a type parameter known only at runtime.

以下是我如何从非泛型类中获取泛型方法的 MethodInfo:

Here is how I would get a MethodInfo for a generic method from a non-generic class:

class MyClass
{
    public void MyMethod<T> (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<object>
        .GetGenericMethodDefinition () // Get MethodInfo for MyClass.MyMethod<>
        .MakeGenericMethod (type);     // Get MethodInfo for MyClass.MyMethod<int>
}

Resolve (typeof (int)).Invoke (new MyClass (), new object[] {3});

现在,如果我想用泛型类尝试类似的东西:

Now if I want to try something similar with a generic class:

class MyClass<T>
{
    public void MyMethod (T arg)
    {
    }
}

static MethodInfo Resolve (Type type)
{
    Expression<Action<MyClass<object>, object>> lambda = (c, a) => c.MyMethod (a);
    MethodCallExpression                        call = lambda.Body as MethodCallExpression;

    return call
        .Method              // Get MethodInfo for MyClass<object>.MyMethod
        .SomeMagicMethod (); // FIXME: how can I get a MethodInfo 
                             // for MyClass<T>.MyMethod where typeof (T) == type?
}

Resolve (typeof (string)).Invoke (new MyClass<string> (), new object[] {"Hello, World!"});

有可能吗?

推荐答案

public class MyClass<T>
{
    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<object>(x => (o) => x.MyMethod(o));
        var genericType = typeof(MyClass<>).MakeGenericType(new[] { type });
        MethodInfo genericTypeMyMethodInfo = genericType.GetMethod(name); // "MyMethod");
        genericTypeMyMethodInfo = genericType.GetMethod(name, new[] { type, typeof(bool) });
        return genericTypeMyMethodInfo;
    }
    public static void Test1()
    {
        Resolve(typeof(string))
            .Invoke(new MyClass<string>(), new object[] { "Hello, World!", true });
        // Resolve(typeof(string))
            .Invoke(new MyClass<string>(), new object[] { "Hello, World!" });
    }
}

要使其成为强类型,您应该简化并使用不同的方法:

To make it strong-typed you should simplify and use different approach:

1) 使用表达式获取动作/方法的name...

1) Get the name of the action / method using expressions...

var name = ActionName<object>(x => (o) => x.MyMethod(o));

2) 然后做不可避免的反射部分

2) Then do the unavoidable reflection part

var genericType = typeof(MyClass<>).MakeGenericType(new[] { type });
MethodInfo genericTypeMyMethodInfo = genericType.GetMethod(name); // "MyMethod");


ActionName 采取与例如类似的方法的地方OnPropertyChanged(x => x.Property)


Where ActionName is taking similar approach as e.g. OnPropertyChanged(x => x.Property)

public static string ActionName<T>(Expression<Func<MyClass<T>, Action<T>>> 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");
    }
}

这篇关于如何使用强类型反射为泛型类的方法查找 MethodInfo?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆