C# 如何通过反射调用没有参数的泛型方法?

C# 如何通过反射调用没有参数的泛型方法?,c#,generics,reflection,C#,Generics,Reflection,假设我有一个这样的类,包含一个带有out参数的泛型方法: public class C { public static void M<T>(IEnumerable<T> sequence, out T result) { Console.WriteLine("Test"); result = default(T); } } Console.WriteLine((int)parameters[1]); //will

假设我有一个这样的类,包含一个带有out参数的泛型方法:

public class C
{
    public static void M<T>(IEnumerable<T> sequence, out T result)
    {
        Console.WriteLine("Test");
        result = default(T);
    }
}
Console.WriteLine((int)parameters[1]); //will get you 0(default(int)).
公共C类
{
公共静态void M(IEnumerable序列,out T结果)
{
控制台写入线(“测试”);
结果=默认值(T);
}
}
通过阅读其他几个问题(和)的答案,我认为我可能能够通过反射调用该方法,如下所示:

// get the method
var types = new[] { typeof(IEnumerable<int>), typeof(int).MakeByRefType() };
MethodInfo mi = typeof(C).GetMethod(
    "M", BindingFlags.Static, Type.DefaultBinder, types, null);

// convert it to a generic method
MethodInfo generic = mi.MakeGenericMethod(new[] { typeof(int) });

// call it
var parameters = new object[] { new[] { 1 }, null };
generic.Invoke(null, parameters);
//获取方法
var types=new[]{typeof(IEnumerable),typeof(int).MakeByRefType()};
MethodInfo mi=typeof(C).GetMethod(
“M”,BindingFlags.Static,Type.DefaultBinder,Type,null);
//将其转换为泛型方法
MethodInfo generic=mi.MakeGenericMethod(new[]{typeof(int)});
//叫它
var参数=新对象[]{new[]{1},null};
generic.Invoke(null,参数);
但是
mi
返回空值。我尝试在
类型
数组中使用
对象
而不是
int
,但这也不起作用


在调用
MakeGenericMethod
之前,如何为泛型方法指定类型(out参数所需)?

您已经传递了将找到
M(IEnumerable,ref int)

您需要找到
M(IEnumerable,ref T)
ref
out
之间的区别只存在于C语言中;反射只有
ref

我不知道该如何通过;您可能需要遍历所有方法才能找到它

在一个不相关的注释中,您需要传递更多的
BindingFlags

BindingFlags.Public | BindingFlags.Static

这将允许您调用该方法:

MethodInfo mi = typeof(C).GetMethod("M");
MethodInfo generic = mi.MakeGenericMethod(new[] { typeof(int) });
var parameters = new object[] { new[]{1},null};
generic.Invoke(null, parameters);
要获取out参数,请执行以下操作:

public class C
{
    public static void M<T>(IEnumerable<T> sequence, out T result)
    {
        Console.WriteLine("Test");
        result = default(T);
    }
}
Console.WriteLine((int)parameters[1]); //will get you 0(default(int)).

这是一个众所周知的问题;要找到该方法,您需要知道其类型参数,但如果不先知道该方法,则无法知道其类型参数

一个明显但不雅观的解决方案是循环使用所有方法,直到找到正确的方法

另一个选项是利用Linq表达式API:

public static MethodInfo GetMethod(Expression<Action> expr)
{
    var methodCall = expr.Body as MethodCallExpression;
    if (methodCall == null)
        throw new ArgumentException("Expression body must be a method call expression");
    return methodCall.Method;
}


...

int dummy;
MethodInfo mi = GetMethod(() => C.M<int>(null, out dummy));
publicstaticmethodinfo-GetMethod(Expression-expr)
{
var methodCall=expr.Body作为MethodCallExpression;
if(methodCall==null)
抛出新ArgumentException(“表达式体必须是方法调用表达式”);
返回methodCall.Method;
}
...
int假人;
MethodInfo mi=GetMethod(()=>C.M(null,out-dummy));
我仍然有兴趣知道用于指定模板类型数组的语法是什么,或者是否不可能

。我认为,如果您有许多这样的
M
s要查看,那么您必须将它们全部获取,然后根据
MethodInfo
s的各种属性和包含的对象进行过滤,例如,在您的特定情况下,尽可能多地使用这些属性:

var myMethodM =
    // Get all the M methods
    from mi in typeof(C).GetMethods()
    where mi.Name == "M"

    // that are generic with one type parameter
    where mi.IsGenericMethod
    where mi.GetGenericArguments().Length == 1
    let methodTypeParameter = mi.GetGenericArguments()[0]

    // that have two formal parameters
    let ps = mi.GetParameters()
    where ps.Length == 2

    // the first of which is IEnumerable<the method type parameter>
    where ps[0].ParameterType.IsGenericType
    where ps[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
    where ps[0].ParameterType.GetGenericArguments()[0] == methodTypeParameter

    // the second of which is ref <the method type parameter>
    where ps[1].ParameterType.IsByRef
    where ps[1].ParameterType.GetElementType() == methodTypeParameter

    select mi;
var myMethodM=
//获取所有的M方法
在typeof(C.GetMethods()中来自mi
其中mi.Name==“M”
//具有一个类型参数的泛型
其中mi.IsGenericMethod
其中mi.GetGenericArguments().Length==1
让methodTypeParameter=mi.GetGenericArguments()[0]
//有两个形式参数
设ps=mi.GetParameters()
其中ps.Length==2
//第一个是IEnumerable
其中ps[0].ParameterType.IsGenericType
其中ps[0]。ParameterType.GetGenericTypeDefinition()==typeof(IEnumerable)
其中ps[0].ParameterType.GetGenericArguments()[0]==methodTypeParameter
//第二个是ref
其中ps[1]。ParameterType.IsByRef
其中ps[1].ParameterType.GetElementType()==methodTypeParameter
选择mi;

从您的答案中不清楚,但是
ref
out
之间的区别在这里不重要,重要的只是泛型类型。@hvd:Yes;我忘了提那件事了。你真正的类有
M
的重载吗?如果没有,您可以只使用
GetMethod
变量,不需要指定参数类型。但这并不能回答您提出的问题。在这个特定的例子中,我可以通过不指定任何类型,只使用名称来解决这个问题,正如@SLaks所建议的那样。我仍然有兴趣知道用于指定模板类型数组的语法是什么,或者是否不可能。我的错误在于我认为有必要传递类型数组,以便使用
out
ref
参数。事实并非如此。。。只要你通过某种方式获得了正确的
MethodInfo
,你就可以将参数数组传递给它,它将设置值。是的,我知道,你的权利一如既往:),我只是介绍了这一点,因为OP没有提及除此之外的任何其他方法,我知道这是一个非常“独特”(lol)的解决方案。