C# 如何通过反射调用没有参数的泛型方法?
假设我有一个这样的类,包含一个带有out参数的泛型方法: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
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)的解决方案。