[英]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.