簡體   English   中英

獲取ICollection的類型參數 <T> 實施課程

[英]Getting the type argument of an ICollection<T> implementing class

我正在.net中編寫一個小的序列化庫。 目標是替換XmlSerialize,但更容易配置,而不會使模型與屬性混亂。

我面臨的問題是我需要在遍歷模型時找到的每個ICollection<T>的類型。 天真的方法是這樣的:

 var theType=myModel.GetType().GetGenericArguments()[0];

但是對於從具有特定T的ICollection<T>派生的類沒有幫助。

public class MyClass:A,ICollection<B>{}

我嘗試使用反射獲取界面

  var iCollectionInterface =
  o.GetType().GetInterfaces()
     .Where(i => i.IsGenericType)
     .Select(i => i.GetGenericTypeDefinition())
     .FirstOrDefault(i => i == typeof(ICollection<>));

但是iCollectionInterface.GetGenericArguments()[0]只是T而不是B因為它只描述了接口的定義而不是它的用法。

有任何想法嗎? 我也需要它用於IDictionary<TKey, TValue>但這基本上是同樣的問題,並將有相同的解決方案。

謝謝!

編輯

謝謝大家,以下是我最終的結果:

public static Type GetTypeParameter(object o, Type typeToSearch, int argumentNumber)
{
    return o.GetType()
            .GetInterfaces()
            .Where(i => i.IsGenericType)
            .Where(i => i.GetGenericTypeDefinition() == typeToSearch)
            .Select(t => t.GetGenericArguments()[argumentNumber])
            .FirstOrDefault();
}

這就是你需要的: Type.GetGenericArguments方法

所以,擁有

class MyDictionary: IDictionary<string, decimal>
{
    ...
}

試試這個擴展方法:

public static Type[] GetClosingArguments<T>(this Type type)
{
    Type iType = typeof(T).GetInterfaces()
                          .FirstOrDefault(i => i.IsGenericType &&
                                     i.GetGenericTypeDefinition() == type);
    if (iType == null)
        return null;
    else
        return iType.GetGenericArguments();
}

像這樣

Type[] types = typeof(IDictionary<,>).GetClosingArguments<MyDictionary>();
if (types != null)
{
    foreach (Type t in types)
        Console.WriteLine(t.Name);
}

或相反亦然:

public static Type[] GetClosingArguments(this Type type, Type baseGenericType)
{
    Type iType = type.GetInterfaces()
                     .FirstOrDefault(i => i.IsGenericType &&
                               i.GetGenericTypeDefinition() == baseGenericType);
    if (iType == null)
        return null;
    else
        return iType.GetGenericArguments();
}

被稱為

Type[] types = typeof(MyDictionary).GetClosingArguments(typeof(IDictionary<,>));

從評論看來,你需要弄清楚如何過濾集合只包括ICollection。 您可以通過以下方式達到目標:

var iCollectionInterfaces =
      from i in o.GetType().GetInterfaces()
      where i.IsGenericType 
            && i.GetGenericTypeDefinition() == typeof(IColection<>)
      select i;

然后,您可以迭代集合,並為每個類型參數執行所需的操作

//same type might implement ICollection<T> more than once
foreach(var collection in iCollectionInterfaces) {
     //More than one is invalid for ICollection<T>
    var T = collection.GetGenericArguments().Single();
    //do what ever you need
}

當然,如果你想讓它更通用。 即支持具有多個類型參數的接口/類型,您需要刪除對Single的調用並替換類型參數的迭代

我認為以下呼叫是問題所在

.Select(i => i.GetGenericTypeDefinition())

你使用已定義泛型參數的閉合泛型類型,然后得到它的通用定義,它是開放的,只知道T 也許你還需要更改FirstOrDefault調用,我不確定封閉類型是否等於ICollection<>

暫無
暫無

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

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