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

Pao*_*sco 3 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,parameterType并且actionType不相等,但是当我检查调试器时,它们看起来完全相同.

为什么这种比较失败了?

Tit*_*mir 9

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

var methodTypeArg = m.GetGenericArguments().First();
var actionType = typeof(Action<>).MakeGenericType(methodTypeArg);
Run Code Online (Sandbox Code Playgroud)

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

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

public void SomeMethod<TMethodArg>(Action<TMethodArg> action)
Run Code Online (Sandbox Code Playgroud)

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

  • @PaoloTedesco我在答案中添加了一些解释,希望事情更清楚.基本上typeof(Action <>)是通用定义.参数永远不属于这种类型,它们只能输入到定义的实例化,即使实例化本身与另一个泛型参数绑定 (2认同)