2011-11-04 67 views
1

我有一堆類都包含一個SharedReadOnly字典。如果我想在類是泛型類型時訪問該字典(例如,當我有一個包裝函數將T作爲所有這些類實現的接口),那麼執行該操作的方法是什麼?當它是一個泛型類型時,從類中獲取共享成員?

基礎研究表明我想做類似GetType(T).GetMember("Dict")的事情,但是這將返回MemberInfo類型,並且不能轉換爲我定義的類型的字典。爲了以這種方式調用功能,可以使用委託+ CreateDelegate + GetMethod。但是,GetMember似乎沒有相應的Create*。或者我錯過了什麼?

如果我將GetMember調用插入到立即窗口,然後使用下標就好像它是一個數組,然後調試輸出說我得到一個字典回來。但如果我在實際功能中使用相同的方法,我試圖寫,然後我得到一個關於System.Reflection.MemberInfo不能轉換爲字典(X,Y)的錯誤

回答

2

你快到了。

GetMember返回所有跟你擦肩而過名成員的陣列(你可以通過使用包含通配符*串並取回多個成員)。因此,在這種情況下,您必須將索引編入返回值以得到您想要的實際MemberInfo

然後,爲了做任何事情,您需要將它轉換爲實際的-Info類型,在這種情況下爲FieldInfo

一旦你得到了FieldInfo,你可以調用GetValue來獲得該字段的實際值。你需要通過NothingGetValue,因爲這個字段是共享的,所以你想得到這個字段值的'實例'根本就不是實例。

最後,您需要將返回值GetValue轉換爲您的實際字典類型,因爲它的類型爲Object

然後你可以看你的字典。

這可能看起來很長,但只是因爲我拼寫出來了 - 如果你很樂意去沒有錯誤檢查(你應該,一旦它工作),這將是最多幾行。

立即窗口「正常工作」的原因是因爲調試器在幕後爲您做了所有這些。這非常有幫助。

+0

好的,這個工程。這是一些醜陋的代碼,但它的工作原理。但它也是_slow _...這很可能是因爲使用了反射,它總是一個表演豬。有沒有辦法緩存查找的一部分,以便未來的調用,而該程序正在運行的特定字典將不必再次執行反射?類似於這個想法是另一個問題,我[問這裏](http://stackoverflow.com/questions/4611890/faster-way-to-convert-from-a-string-to-generic-type-t- when-t-is-a-valueetype/4678430#4678430),它使用委託緩存函數指針。 – Kumba

+0

PS,我還沒有探索過的一個想法是在基類中的每個子類中定義另一個存根函數(請參閱我對@competent_tech的評論,瞭解這些類都是什麼),拍攝該子類上的接口,並將該類綁定進入更高級的父類來調用主代碼。如果我無法緩存反射查找,或者這種緩存仍然很慢,那麼這可能是一種替代路線,但仍不會導致太多的函數調用開銷。真的,這樣做的真正目的是爲了避免在我的項目中的字典中出現'.Item'多個語句到'.ContainsKey'。 – Kumba

+0

好吧,我只是對存根函數的想法進行了基準測試,它完全吸引了我的原始實現,儘管在覈心上,它添加了_two_函數調用,並仍然在字典上執行'.ContainsKey'後跟'.Item'。在10萬次的緊密時序循環中,比直接調用'.ContainsKey'和'.Item'要快200ms。我想知道是否通過將這些調用移動到包含子類中,我以某種方式激活了.NET內部的緩存機制,從而提高了性能? – Kumba

0

我不確定您的原始請求是否可能,但我會採取的解決方案將創建一個接口來檢索屬性,並讓每個類實現此接口來返回屬性。我們在泛型類中廣泛使用這種機制。

+0

這就是我爲很多事情做的事情。在少數情況下,我實現了通過使用委託來獲取方法的擴展。在這種情況下,字典是'Shared',所以我不能使用它的接口聲明(爲什麼MS不允許爲僅使用共享/靜態成員的類提供一組共享/靜態接口) 。 – Kumba

+0

您實際上可以使用一個接口來提供這些信息,我們一直都在這樣做。您不會直接在字典上創建接口,您將使用實現該接口的實例成員(屬性或函數),然後使用該成員來返回共享成員。唯一的缺點是,如果在通過接口檢索數據時尚未擁有實現接口的類的實例,但創建一次性實例以訪問該接口應該很容易。 –

+0

除了我的這些類永遠不會用作實例。它們中的所有內容都是共享的,並且只有共享成員纔會被引用。這是一個黑客做更好的枚舉,我記錄在另一個問題,我打開了一會兒回來[這裏](http://stackoverflow.com/q/4180742/482691)。自那時起,它們已經發展了很多,並且我甚至用少量的性能處罰爲特定的幾個開發了按位功能。因此,爲什麼我不能使用接口作爲這些類的契約(只有在每個基本級Enum類中定義的'Enums'子類)。 – Kumba