2011-07-22 66 views
1

假設我有一個List<IMyInterface> ...類型參數 - 從獲取類型T的具體類型:IMyInterface的

我有實現IMyInterface三類:MyClass1MyClass2MyClass3

我有一個只讀的字典:

private static readonly Dictionary<Type, Type> DeclarationTypes = new Dictionary<Type, Type> 
{ 
    { typeof(MyClass1), typeof(FunnyClass1) }, 
    { typeof(MyClass2), typeof(FunnyClass2) }, 
    { typeof(MyClass3), typeof(FunnyClass3) }, 
}; 

我還有一個接口,IFunnyInteface<T> where T : IMyInterface

我有一個方法:

public static IFunnyInterface<T> ConvertToFunnyClass<T>(this T node) where T : IMyInterface 
{ 
    if (DeclarationTypes.ContainsKey(node.GetType())) { 
     IFunnyInterface<T> otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node); 
     return otherClassInstance; 
    } 
    return null; 
} 

我想打電話給FunnyClasses的構造和插入的參數我MyClass的對象。我不想知道它是哪個對象:我只想用MyClass作爲參數實例化一些FunnyClass。

當我打電話ConvertToFunnyClass會發生什麼,TIMyInterface類型的,當我嘗試將其轉換爲FunnyInterface<T>,它說我不能轉換FunnyClass1,例如,以FunnyInterface<IMyInterface>

我目前的解決方法(不一個美麗的),是這樣的:

public static dynamic ConvertToFunnyClass<T>(this T node) where T : IMyInterface 
{ 
    if (DeclarationTypes.ContainsKey(node.GetType())) { 
     var otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node); 
     return otherClassInstance; 
    } 
    return null; 
} 

而且,因爲返回類型爲dynamic我不喜歡它,所以當我從別的地方訪問它,我不知道它是什麼類型的,我失去了智能感知和東西。我也不知道任何性能影響。

任何線索?

在此先感謝!

分辨率

由於我使用C#4.0中,我可以停止鑄造用協方差(輸出位置只)的錯誤,所以我改變了我的IFunnyInterface

IFunnyInteface<out T> where T : IMyInterface 

謝謝大家答覆。

+0

這個例子有很多,所以如果我錯過了一個關鍵點,請原諒我。 FunnyClass1是否實現了IFunnyInterface ? –

+0

'FunnyClass1'實現'IFunnyInterface '。 –

回答

1

本質上,你的問題是你試圖將FunnyInterface<T>轉換爲FunnyInterface<IMyInterface>。正如已經多次提到的(一個例子是here,更多信息here),這在大多數情況下是無效的。只有在.NET 4中,當泛型類型是接口或委託,並且類型參數已明確聲明爲inout的變體時,是否可以執行此轉換。

FunnyInterface實際上是一個接口?

+0

我的錯誤,FunnyInterface ='IFunnyInterface',我拼寫錯誤 –

1

thecoop答案正好指出你爲什麼不能這樣做。

一個清潔的解決問題的方法(除了使用動態)將是一個基礎的非泛型接口:

public interface IFunnyInterfaceBase 
{ 
} 

public interface IFunnyInteface<T> : IFunnyInterfaceBase 
    where T : IMyInterface 
{ 
} 

而且你需要移動你的代碼從IFunnyInteface到IFunnyInterfaceBase使用方法簽名。

這樣你就可以寫這樣的事:

MyClass2 c2 = new MyClass2(); 
IFunnyInterfaceBase funnyInstance = c2.ConvertToFunnyClass(); 

您在代碼中有你說的例外是不是由於擴展方法簽名本身(方法是罰款)..它是由你的左值類型(你用來存儲它的返回值的變量的類型)產生的!

顯然這個解決方案只適用於你可以修改IFunnyInterface的源代碼!

+0

+1非常感謝Fulvio,我只是選擇了使用thecoop建議的解決方案,因爲我使用的是.NET 4.0 –