2013-11-25 105 views
3

我正在嘗試在運行時創建泛型對象。到目前爲止,我已經能夠創建它,但我無法弄清楚如何投射它。我所擁有的是enum對象,我想生成EnumMapper,它將枚舉值轉換爲自定義字符串以映射到遺留數據庫。如何在不知道類型的情況下投射泛型類型

Type enumType = myEnum.GetType(); 
Type enumMapperType = typeof(EnumMapper<>) 
         .GetGenericTypeDefinition().MakeGenericType(enumType); 
var mapper = Activator.CreateInstance(enumMapperType); // OK 
EnumMapper<> mapper = (EnumMapper<>) Activator.CreateInstance(enumMapperType); // Error 

當我檢查在調試器是創建如我所期望的目標,但我怎麼能投,所以我可以用它?

類:

public class EnumMapper<T> : IEnumMapper<T> 

接口:

public interface IEnumMapper<T> 
{ 
    T EnumValue(string value); 

    bool HasEnumValue(string stringValue); 

    bool HasStringValue(T enumValue); 

    string StringValue(T enumValue); 
} 

Error 2 ; expected \EnumMapperTest.cs 36 
Error 4 ; expected \EnumMapperTest.cs 36 
Error 1 Invalid expression term '>' \EnumMapperTest.cs 36 
Error 3 Invalid expression term '>' \EnumMapperTest.cs 36 
Error 34 Only assignment, call, increment, decrement, and new object expressions can be used as a statement \EnumMapperTest.cs 36 
Error 36 The name 'mapper' does not exist in the current context \EnumMapperTest.cs 36 
Error 35 Using the generic type 'EnumMapper<T>' requires 1 type arguments \EnumMapperTest.cs 36 
Error 37 Using the generic type 'EnumMapper<T>' requires 1 type arguments \EnumMapperTest.cs 36 
+1

你得到的具體錯誤是什麼? –

+1

我敢肯定這裏有重複的內容......但是您能否給我們提供更多關於您試圖用實例實現的信息,以及您是否控制了泛型? (例如,你可以創建一個非泛型基類型嗎?) –

+0

EnumMapper <> - 什麼是類型? – progpow

回答

2

據我所知,你需要的確切的事情是不可能在C#。基本上,您需要一種基於常規非泛型參數的值具有不同類型或返回變量的方法,即如果參數是typeof(Enum1),那麼結果變量是EnumMapper<Enum1>,如果參數是typeof(Enum2),比結果變量是EnumMapper<Enum2>

但是,您可以使用泛型參數來做到這一點,因爲泛型是關於編譯時信息的,而且在運行時只有這個值,所以在這種情況下不能使用它們。

你可以做什麼(以及我所做的)是使用動態代碼來解決這個問題,小心地儘快進入靜態類型的土地(動態真是具有感染力,有人說像一個微笑,有人說像病毒一樣):

public dynamic GetMapperObject(Type enumType) 
{ 
    Type enumMapperType = typeof(EnumMapper<>) 
          .GetGenericTypeDefinition() 
          .MakeGenericType(enumType); 
    var mapper = Activator.CreateInstance(enumMapperType); 
    return mapper; 
} 

與調用如下代碼:

var mapper = GetMapperObject(enumType); 
//dynamic call, bind the resut to a statically typed variable 
bool result = mapper.HasEnumValue("SomeStringValue") 

(舊回答,只是增加了間接的另一個層面的問題:))

你可以包裝都在一個通用的方法,這樣的事情:

public EnumMapper<T> GetMapperObject<T>() 
{ 
    Type enumType = typeof(T); 
    Type enumMapperType = typeof(EnumMapper<>) 
          .GetGenericTypeDefinition() 
          .MakeGenericType(enumType); 
    var mapper = Activator.CreateInstance(enumMapperType); 
    return mapper as EnumMapper<T>; 
} 

var mapper = GetMapperObject<EnumMapperTestEnum>(); 

調用它。然而,如果你只有枚舉一個值,你可以使用類型推斷,是這樣的:

//everything is the same, just different signature 
public EnumMapper<T> GetMapperByExample<T>(T item) 
{ 
    Type enumType = typeof(T); 
    Type enumMapperType = typeof(EnumMapper<>) 
          .GetGenericTypeDefinition() 
          .MakeGenericType(enumType); 
    var mapper = Activator.CreateInstance(enumMapperType); // OK 
    return mapper as EnumMapper<T>; 
} 

與類型推斷稱之爲

var mapper = GetMapperByExample(EnumMapperTestEnum.SomeValue); 
+2

問題是我沒有T,我得到一個枚舉,然後想要爲此枚舉創建一個枚舉映射器... – uncletall

+1

這適用於您將代碼替換爲調用並提取方法。 – SWeko

+0

好吧,我想我的問題不清楚。我沒有T型,只有enumType。這只是爲了測試的目的,我做的類型(T) – uncletall

相關問題