2012-08-28 44 views
3

首先讓我說,我想要做的是獲取泛型類中的屬性值,該屬性值可以由繼承自類的屬性重寫。可以將它看作是基類中的默認值,類的繼承者可以覆蓋它們以設置它們自己的默認值。如何使用反射創建通用對象

我試圖直接在類型上使用反射,使用System.Reflection.FieldInfo.GetValue但這不適用於具有泛型類型的類。所以我認爲我需要實例化這個類,以便能夠看到它的價值。

我通過讀取bin中的Dll並使用Reflection來查找從我的界面繼承的類型,從而檢索到「類型」。

我使用.NET 4.5

這裏是文檔,似乎像它解釋正是我需要做的 http://msdn.microsoft.com/en-us/library/b8ytshk6.aspx

在本文檔中,我可以看到的唯一的區別是我們如何得到我們的類型,我看着在箱子的類型,他們根本typeof運算()調用,因爲類型是如此複雜,似乎這可能是一個可能不匹配,但我看不出有什麼缺失(如果有的話)

foreach (var item in types) 
{ 
    var ts = item.GetField("DefaultTimeToExpire"); 
    Type[] typeArguments = item.GetGenericArguments(); 
    if (ts != null) 
    { 
     var t = item.MakeGenericType(typeArguments); 
     var obj = Activator.CreateInstance(t); 
     var timespan = obj.DefaultTimeToExpire; 
     subscriberInfos.Add(new Tuple<string, Type, TimeSpan>(item.Name, item, timespan)); 
    } 
} 

我調用GetField查找迄今爲止有一個字段爲「DefaultTimeToExpire」的項目,這部分很適合找到我需要的類型。 接下來我調用GetGenericArguments,它返回一個期望的Arguments類型的數組。 後來我打電話MakeGenericType 終於創建實例至極給我的錯誤消息

「因爲Type.ContainsGenericParameters是真的無法創建BusinessLogic.TestSubscriberXXX`1 [信息]的一個實例。」

這看起來正是我應該做的。 謝謝

+0

您的'typeArguments'可能沒有足夠的類型來設置所有泛型的類型參數嗎? –

+0

奇怪的錯誤,很難猜測你是如何以開放式結束的。快捷方式是使用Activator.CreateInstance(item.GetType())。 –

回答

4

爲了實例化泛型類型,您需要知道應該替代其類型參數的實際值(類型)。作爲反映形式的GetGenericArguments()方法僅給出參數的類型,而不是它們的實際值。價值取決於你......這就是泛型的全部要點。

如果item是像List<T>一個類型然後item.GetGenericArguments()將返回含有假「類型」表示類型參數T(連同其IsGenericParameter屬性設置爲true)的陣列。因此,將該參數類型傳遞迴item.MakeGenericType()將簡單地創建另一個與原始等效的開放式泛型類型。要關閉泛型類型以便可以實例化,您需要提供一個實際的(非參數)類型參數,例如int

例如,typeof(List<>).MakeGenericType(typeof(int))將返回typeof(List<int>),而typeof(List<>).MakeGenericType(typeof(List<>).GetGenericArguments())將僅返回typeof(List<>)。這就是你的代碼中發生的事情。

對不起,如果這有點不透明,我不知道該怎麼解釋。最重要的是,像List<T>這樣的類型只有在您想要替換的類型代替T時纔有用。

+0

當我調用GetGenericArguments()時,Item是類似列表的類型,我檢查返回的內容,它返回一個我期待的類型。用戶」。可疑的一件事是FullName爲空,儘管它具有Assembly的完全限定名 – Noel

+0

FullName爲null很奇怪......我從來沒有見過這種情況。如果它返回User(而User是一個實際的類型,而不是一個類型參數),那麼你已經有了一個封閉的泛型類型。然後,您應該可以簡單地執行'Activator.CreateInstance(item)''。 – luksan

+0

好吧,我不知道爲什麼我無法創建正確的泛型類型來允許CreateInstance工作,但我已經解決了我的問題。這段代碼實際上是在一個泛型類中,它實現了我試圖創建的類型作爲我的泛型類型。所以我可以寫:var typeArg = typeof(T); var t = item.MakeGenericType(typeArg); ISubscriber subscriber =(ISubscriber )Activator.CreateInstance(t); var timespan = subscriber.DefaultTimeToExpire; subscriberInfos.Add(new Tuple (item.Name,item,timespan)); ' – Noel

相關問題