2013-07-08 42 views
19

我有一個類需要一個通用類型作爲其初始化的一部分。從一個C#類型變量初始化一個通用變量

public class AnimalContext<T> 
{ 
    public DoAnimalStuff() 
    { 
     //AnimalType Specific Code 
    } 
} 

我現在就可以做的是

AnimalContext<Donkey> donkeyContext = new AnimalContext<Donkey>(); 
AnimalContext<Orca> orcaContext = new AnimalContext<Orca>(); 

但我需要/想要做的就是能夠申報初始化爲僅在運行時已知的類型的AnimalContext。例如,

Animal a = MyFavoriteAnimal(); //returns an instance of a class 
           //implementing an animal 
AnimalContext<a.GetType()> a_Context = new AnimalContext<a.GetType()>(); 
a_Context.DoAnimalStuff(); 

這甚至可能嗎?我似乎無法找到這個在線的答案。

回答

20

你所說的這部分意味着可能是:

new AnimalContext<a.GetType()>(); 

顯然,準確的語法是錯誤的,我們會得到一點,但它可以構建一個通用的實例鍵入運行時間當您不知道類型參數時,直到運行時間

您通過這部分的意思是

AnimalContext<a.GetType()> a_Context 

也就是說,它是不可能一個變量的類型爲泛型類型,如果你不知道編譯時的類型參數。泛型是編譯時間構造,並且依賴於在編譯時可用的類型信息。鑑於此,如果在編譯時不知道類型,則會失去泛型的所有好處。

現在,構建在運行時泛型類型,當你不知道的類型,直到運行時的一個實例,你可以說:

var type = typeof(AnimalContext<>).MakeGenericType(a.GetType()); 
var a_Context = Activator.CreateInstance(type); 

注意,編譯時a_contextobject。您必須將a_context轉換爲定義您需要訪問的方法的類型或接口。通常你會看到人們在這裏做的是通用類型AnimalContext<T>實現一些接口(比如IAnimalContext繼承自定義它們所需方法的非泛型基類(如AnimalContext)(這樣就可以投射a_context到接口或非泛型基類)。另一種選擇是使用dynamic。但是請記住,在這種情況下,您有泛型類型的好處

+3

回答的每個人都給出了比以前的答案提供了更多信息的答案。所有這些都是正確的,並且質量很好,但只有一個可以被選爲答案,所以我選擇了這個最具描述性的一個。我想感謝所有回答的人,並且我感謝所有的幫助(特別是在星期天晚上的晚些時候)。 –

+0

如果我的類不是泛型的,但是裏面的方法是什麼,我將如何使用MakeGenericType –

6

您可以通過使用MakeGenericType方法使用與普通的反射式,並採取dynamic關鍵字adavantage:

var type = typeof (AnimalContext<>).MakeGenericType(a.GetType()); 
dynamic a_Context = Activator.CreateInstance(type); 

所以你可以撥打:

a_Context.DoAnimalStuff(); 

或者使用反射再次調用方法:

type.GetMethod("DoAnimalStuff").Invoke(a_Context, null); 
5

您需要創建類型usin g Reflection然後調用該類型。喜歡的東西:

Animal a = MyFavoriteAnimal(); 
var contextType = typeof(EsbRepository<>).MakeGenericType(a.GetType()); 

dynamic context = Activator.CreateInstance(contextType); 
context.DoAnimalStuff(); 

使用動態意味着上下文變量將在運行時進行評估,允許您致電DoAnimalStuff方法。