簡體   English   中英

如何通過反射調用帶參數的泛型方法?

[英]How do you call a generic method with out parameters by reflection?

假設我有一個這樣的類,包含帶out參數的泛型方法:

public class C
{
    public static void M<T>(IEnumerable<T> sequence, out T result)
    {
        Console.WriteLine("Test");
        result = default(T);
    }
}

從閱讀答案到其他幾個問題( 如何使用反射調用泛型方法?使用out參數反映靜態重載方法 ),我想我可以通過反射調用方法,如下所示:

// 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回來了。 我嘗試在types數組中使用object而不是int ,但這也不起作用。

在調用MakeGenericMethod 之前 ,如何為泛型方法指定類型(out參數所需)?

您已經傳遞了將找到M<T>(IEnumerable<int>, ref int)
你需要找到M(IEnumerable<T>, ref T)refout之間的區別只存在於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參數:

Console.WriteLine((int)parameters[1]); //will get you 0(default(int)).

我仍然有興趣知道指定模板類型數組的語法是什么,或者如果不可能的話

我認為不可能將這種詳細的類型規范傳遞給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;

這是一個眾所周知的問題; 要找到該方法,您需要知道它的類型參數,但是如果不先了解方法就無法知道它的類型參數...

一個明顯但不優雅的解決方案是循環使用所有方法,直到找到正確的方法。

另一個選擇是利用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));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM