假设我有一个这样的类,包含带有out参数的泛型方法:
public class C
{
public static void M<T>(IEnumerable<T> sequence, out T result)
{
Console.WriteLine("Test");
result = default(T);
}
}
从阅读答案到其他几个问题(How to use reflection to call generic Method?和Reflection on a static overloaded method using an out parameter),我想我可以通过反思调用方法,如下所示:
// 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);
但是mi
回来了。我尝试在object
数组中使用int
代替types
,但这也不起作用。
如何在调用MakeGenericMethod
之前为通用方法指定类型(out参数所需)?
答案 0 :(得分:3)
您已经传递了会找到M<T>(IEnumerable<int>, ref int)
的参数
您需要找到M(IEnumerable<T>, ref T)
(ref
和out
之间的区别仅存在于C#语言中;反射仅存在ref
)。
我不确定如何通过;您可能需要遍历所有方法才能找到它。
在不相关的说明中,您需要传递更多BindingFlags
:
BindingFlags.Public | BindingFlags.Static
答案 1 :(得分:3)
这将让您调用方法:
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参数:
Console.WriteLine((int)parameters[1]); //will get you 0(default(int)).
答案 2 :(得分:3)
我仍然有兴趣知道指定模板类型数组的语法是什么,或者是否可能
I don't think it's possible to pass that kind of detailed type specification to GetMethod[s]
。我想如果你有一些这样的M
要查看,你必须得到它们然后按MethodInfo
和包含的对象的各种属性进行过滤,例如尽可能多的在你的特定情况下是必要的:
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;
答案 3 :(得分:1)
这是一个众所周知的问题;要找到该方法,您需要知道它的类型参数,但是如果不先知道方法就无法知道它的类型参数......
一个明显但不优雅的解决方案是循环使用所有方法,直到找到合适的方法。
另一个选择是利用Linq Expression 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));