使用反射比较通用参数类型

时间:2017-08-29 13:13:11

标签: c# reflection .net-core

我希望获得一个使用反射接受Action<T>参数的方法定义。我使用.NET核心1.1。

由于该类有两个同名的方法,我试图检查接受参数的类型,以确保我得到正确的方法定义(而不是其他重载),但这种比较似乎不起作用。

以下是一些显示此问题的代码:

using System;
using System.Linq;
using System.Reflection;

class ReflectMe {
    public void SomeMethod<T>(Action<T> action) {
        action(default(T));
    }
    public T SomeMethod<T>() {
        return default(T);
    }
}

class Program {
    static void Main(string[] args) {
        var reflectedMethod = typeof(ReflectMe).GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Instance)
            .Where(m => m.Name == "SomeMethod" && m.IsGenericMethodDefinition)
            .Where(m => {
                var parameters = m.GetParameters();
                if (parameters.Count() != 1) {
                    // this filters out the 1st method
                    return false;
                }
                var actionType = typeof(Action<>);
                var parameterType = parameters[0].ParameterType;
                if (parameterType == actionType) { 
                    // this is always false, even if in the debugger both
                    // types are displayed as System.Action`1[T]
                    return true;
                }
                return false;
            })
            .FirstOrDefault();
    }
}

问题是parameterTypeactionType不相等,但是当我检入调试器时,它们看起来完全相同。

为什么这种比较失败?

1 个答案:

答案 0 :(得分:8)

您需要实例化Action<T>的泛型定义以使用该方法的泛型参数:

var methodTypeArg = m.GetGenericArguments().First();
var actionType = typeof(Action<>).MakeGenericType(methodTypeArg);

注意:我现在没有.NET Core 1.1,我希望api是一样的,但是你的问题在任何.NET版本中都是一样的。

如果将泛型参数的名称更改为方法,则需要调用MakeGenericType的原因变得更加明显:

public void SomeMethod<TMethodArg>(Action<TMethodArg> action)

然后typeof(Action<>) != typeof(Action<TMethod>)变得更加明显。您正在比较Action<>的通用定义(它位于T上)与泛型方法TMethod的泛型参数(SomeMethod)的定义实例化/ p>

相关问题