簡體   English   中英

如何使用反射從 static class 獲得特定的泛型方法重載?

[英]How do you get specific generic method overload from static class using reflection?

所以我有一個 static class:

class static EnumHelper {
   public string GetCode<E>(E value) where E: struct {}

   public string GetCode<E>(E? value) where E: struct {}
}

但是使用:

typeof(EnumHelper).GetMethod("GetCode")

總是返回這個錯誤:

System.Reflection.AmbiguousMatchException:找到不明確的匹配項。

但是,我不能直接使用提供“參數類型”的 GetMethod 的重載,因為參數類型基於方法本身中定義的泛型類型參數。

目標是:

//given parameter: T item
MethodInfo mi = typeof(EnumHelper).GetMehod("GetCode");
mi.MakeGenericMethod(typeof(T));
mi.Invoke(null, new object[] {item});

但我在這個等式的“GetMethod”部分遇到了麻煩。

謝謝。

最終,您將需要手動消除它們之間的歧義,也許通過使用Nullable.GetUnderlyingType並測試它是否是nullnot null ,在它們之間進行選擇。 例如,查找E value版本:

var method = typeof(EnumHelper).GetMethods(BindingFlags.Public | BindingFlags.Static)
  .Single(method => method.Name == nameof(EnumHelper.GetCode)
  && Nullable.GetUnderlyingType(method.GetParameters().Single().ParameterType) is null);

相同但is not null給你E? 版本。

EnumHelper有兩個同名的不同方法,因此“默認” GetMethod無法在它們之間進行選擇。 您需要手動找出T的可空性和所需的方法。

根據您使用的框架版本,您可以對所有方法執行過濾:

var type = typeof(T);
var sourceTypeNullable = Nullable.GetUnderlyingType(type) != null;
var mi = typeof(EnumHelper)
   .GetMethods()
   .Where(mi => mi.Name == "GetCode")
   .Where(mi => mi.GetParameters() == 1)
   .Where(mi => sourceTypeNullable == (Nullable.GetUnderlyingType(mi.GetParameters()[0].ParameterType) != null))
   .Single();

var constructed = mi.MakeGenericMethod(Nullable.GetUnderlyingType(type) ?? type);
constructed.Invoke(...);

或使用Type.MakeGenericMethodParameter (自 .NET Core 2.1 起可用),它允許構建通用參數描述符並將其傳遞給GetMethod重載,接受表示搜索方法參數的Type對象集合:

var genericType = Type.MakeGenericMethodParameter(0);
genericType = sourceTypeNullable 
   ? Type.MakeGenericSignatureType(typeof(Nullable<>), genericType) // or typeof(Nullable<>).MakeGenericType(genericType) for pre 3.0 versions
   : genericType;
var mi = typeof(EnumHelper).GetMethod(nameof(EnumHelper.GetCode), new[] {genericType});
constructed = mi.MakeGenericMethod(Nullable.GetUnderlyingType(type) ?? type);

您可以根據參數的類型和類型參數是否相同,select 一個或另一個:

var mi = (from m in typeof(EnumHelper).GetMethods()
        where m.Name == "GetCode"
        let targ = m.GetGenericArguments()[0]
        let param = m.GetParameters()[0].ParameterType
        where targ != param // and == for the non-nullable version
        select m).Single();

    Type tArg = typeof(ConsoleColor);
    var value = ConsoleColor.Black;
    mi.MakeGenericMethod(tArg).Invoke(null, new object[] {value});

另請參閱此處的實時示例。

暫無
暫無

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

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