C#:按类型的GetMethod(泛型列表)

C#:按类型的GetMethod(泛型列表),c#,system.reflection,C#,System.reflection,我有一个包含几个泛型重载方法的类。我试图通过它的参数类型得到一个特定的参数。当我坚持使用前两个参数(使用int和string类型的参数)时,这相对容易做到。但无论我做什么,我都不能让我的程序注意到第三个,它是为通用列表设计的。我是否使用了错误的类型参数?如果是,正确的方法是什么 /* rest of code */ static void Main(string[] args) { MethodInfo method = typeof(c).Get

我有一个包含几个泛型重载方法的类。我试图通过它的参数类型得到一个特定的参数。当我坚持使用前两个参数(使用int和string类型的参数)时,这相对容易做到。但无论我做什么,我都不能让我的程序注意到第三个,它是为通用列表设计的。我是否使用了错误的类型参数?如果是,正确的方法是什么

/* rest of code */
    static void Main(string[] args) {
        MethodInfo method =
            typeof(c).GetMethod("m", new Type[] { typeof(int) });

        Console.WriteLine(method);

        method =
            typeof(c).GetMethod("m", new Type[] { typeof(String) });

        Console.WriteLine(method);

        method =
            typeof(c).GetMethod("m", new Type[] { typeof(IEnumerable<>) });

        Console.WriteLine(method);

        Console.ReadKey();
    }
}

static class c
{
    public static void m<T>(int i)
    {
    }

    public static void m<T>(String s)
    {
    }

    public static void m<T>(IEnumerable<T> Ls)
    {
    }
}
/*代码的其余部分*/
静态void Main(字符串[]参数){
MethodInfo方法=
typeof(c).GetMethod(“m”,新类型[]{typeof(int)});
控制台写入线(方法);
方法=
typeof(c).GetMethod(“m”,新类型[]{typeof(String)});
控制台写入线(方法);
方法=
typeof(c).GetMethod(“m”,新类型[]{typeof(IEnumerable)});
控制台写入线(方法);
Console.ReadKey();
}
}
静态c类
{
公共静态无效m(int i)
{
}
公共静态void m(字符串s)
{
}
公共静态void m(IEnumerable Ls)
{
}
}

简短版本:
typeof(IEnumerable)
typeof(IEnumerable)
不同(对于某些
T

更长的版本:没有方法
void c.m(IEnumerable Ls)
,只有泛型参数为特定类型(运行时存在)的重载,其中由于某些代码引用泛型方法的实例化,抖动需要创建方法

在测试代码中向泛型方法的某个实例添加一个调用,然后对该实例执行
GetMethod

考虑以下几点:

using System.Collections.Generic;
using System.Linq;
using static System.Console;

class Methods {
    public static void M(int x)     {
        // no-op
    }

    public static void M<T>(IEnumerable<T> x)     {
        // no-op
    }
}

class Program {
    static void Main(string[] args)  {
        Methods.M(0);
        Methods.M(new[] { "a", "b" });

        ShowAllM();
    }

    public static void ShowAllM() {
        var tm = typeof(Methods);
        foreach (var mi in tm.GetMethods().Where(m => m.Name == "M"))
        {
            WriteLine(mi.Name);
            foreach (var p in mi.GetParameters())
            {
                WriteLine($"\t{p.ParameterType.Name}");
            }
        }
    }
}
使用System.Collections.Generic;
使用System.Linq;
使用静态系统控制台;
类方法{
公共静态void M(int x){
//无操作
}
公共静态void M(IEnumerable x){
//无操作
}
}
班级计划{
静态void Main(字符串[]参数){
方法:M(0);
方法:M(新的[]{“a”,“b”});
ShowAllM();
}
公共静态void ShowAllM(){
var tm=类型(方法);
foreach(tm.GetMethods()中的var mi,其中(m=>m.Name==“m”))
{
WriteLine(mi.Name);
foreach(mi.GetParameters()中的var p)
{
WriteLine($“\t{p.ParameterType.Name}”);
}
}
}
}
它产生输出:

M Int32 M IEnumerable`1 M Int32 M IEnumerable`1 注意,通用重载只产生一个结果。如果将对
M(…)
的调用添加到
Main
中,则输出相同

对于反射,只有一个方法,它的参数反映了它的“开放泛型”性质,但这与使用开放泛型类型(例如,
IEnumerable
)调用并不完全相同,因为开放类型是不可实例化的


(我在这里捏造了很多技术细节。看看
typeof(IEnumerable)
typeof(IEnumerable)
在调试器中的区别是很有帮助的)

简短版本:
typeof(IEnumerable)
typeof(IEnumerable)
(对于某些
T

更长的版本:没有方法
void c.m(IEnumerable Ls)
,只有泛型参数为特定类型(运行时存在)的重载,其中由于某些代码引用泛型方法的实例化,抖动需要创建方法

在测试代码中向泛型方法的某个实例添加一个调用,然后对该实例执行
GetMethod

考虑以下几点:

using System.Collections.Generic;
using System.Linq;
using static System.Console;

class Methods {
    public static void M(int x)     {
        // no-op
    }

    public static void M<T>(IEnumerable<T> x)     {
        // no-op
    }
}

class Program {
    static void Main(string[] args)  {
        Methods.M(0);
        Methods.M(new[] { "a", "b" });

        ShowAllM();
    }

    public static void ShowAllM() {
        var tm = typeof(Methods);
        foreach (var mi in tm.GetMethods().Where(m => m.Name == "M"))
        {
            WriteLine(mi.Name);
            foreach (var p in mi.GetParameters())
            {
                WriteLine($"\t{p.ParameterType.Name}");
            }
        }
    }
}
使用System.Collections.Generic;
使用System.Linq;
使用静态系统控制台;
类方法{
公共静态void M(int x){
//无操作
}
公共静态void M(IEnumerable x){
//无操作
}
}
班级计划{
静态void Main(字符串[]参数){
方法:M(0);
方法:M(新的[]{“a”,“b”});
ShowAllM();
}
公共静态void ShowAllM(){
var tm=类型(方法);
foreach(tm.GetMethods()中的var mi,其中(m=>m.Name==“m”))
{
WriteLine(mi.Name);
foreach(mi.GetParameters()中的var p)
{
WriteLine($“\t{p.ParameterType.Name}”);
}
}
}
}
它产生输出:

M Int32 M IEnumerable`1 M Int32 M IEnumerable`1 注意,通用重载只产生一个结果。如果将对
M(…)
的调用添加到
Main
中,则输出相同

对于反射,只有一个方法,它的参数反映了它的“开放泛型”性质,但这与使用开放泛型类型(例如,
IEnumerable
)调用并不完全相同,因为开放类型是不可实例化的


(我在这里捏造了很多技术细节。查看
typeof(IEnumerable)
typeof(IEnumerable)
在调试器中的区别是很有帮助的)

第三个方法的签名是
m(IEnumerable)
,但您的示例显示了试图找到一个签名为
m(IEnumerable)的方法的尝试。)

typeof(IEnumerable)
typeof(IEnumerable)
之间的区别在于前者是泛型类型,第二个是泛型类型定义,它们不是一回事。泛型类型由泛型类型定义和泛型类型参数确定

考虑到这一点,您可能希望使用:

method =
        typeof(c).GetMethod("m", new Type[] { typeof(IEnumerable<MyType>) });
方法=
typeof(c).GetMethod(“m”,新类型[]{typeof(IEnumerable)});
并替换将传递到方法中的枚举类型

另一方面,如果您事先不知道可枚举的类型,则可以获取泛型方法定义,并在需要时生成可用的泛型方法:

methodDef =
        typeof(c).GetMethod("m", new Type[] { typeof(IEnumerable<object>) }).GetGenericMethodDefinition();
method = methodDef.MakeGenericMethod(new Type[] { typeof(MyType) });
methodDef=
typeof(c).GetMethod(“m”,新类型[]{typeof(IEnumerable)})。