3

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

public class C
{
    public static void M<T>(IEnumerable<T> sequence, out T result)
    {
        Console.WriteLine("Test");
        result = default(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);

但是mi回来为空。我试过在数组中使用object而不是,但这也不起作用。inttypes

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

4

4 回答 4

4

这将让您调用该方法:

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)).
于 2013-07-31T00:29:24.967 回答
3

您已经传递了可以找到的参数M<T>(IEnumerable<int>, ref int)
你需要找到(和M(IEnumerable<T>, ref T)之间的区别只存在于C#语言中;反射只有)。refoutref

我不确定如何通过它;您可能需要遍历所有方法才能找到它。

在不相关的说明中,您需要传递更多BindingFlags

BindingFlags.Public | BindingFlags.Static
于 2013-07-30T21:41:46.507 回答
3

我仍然想知道指定模板类型数组的语法是什么,或者是否不可能

我认为不可能将那种详细的类型规范传递给GetMethod[s]. 我认为,如果您有许多这样M的 s 需要查看,则必须全部获取它们,然后通过MethodInfos 和包含的对象的各种属性进行过滤,例如,在您的特定情况下需要尽可能多的内容:

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;
于 2013-07-31T08:56:47.680 回答
1

这是一个众所周知的问题;要找到方法,你需要知道它的类型参数,但是不知道方法你不能知道它的类型参数...

一个明显但不优雅的解决方案是遍历所有方法,直到找到正确的方法。

另一种选择是利用 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));
于 2013-07-31T08:55:49.123 回答