2008-09-15 41 views
11

我正在使用ChannelFactory編程WCF,它需要一個類型才能調用CreateChannel方法。例如:動態創建模板的通用類型

IProxy proxy = ChannelFactory<IProxy>.CreateChannel(...); 

在我的情況我做了路由,所以我不知道我的頻道工廠將使用什麼類型。我可以解析一個消息頭來確定類型,但是我在那裏碰到了一堵磚牆,因爲即使我有一個Type I的實例也無法通過ChannelFactory期望的泛型類型。

簡單來說重申這個問題將是我試圖做這樣的事情的另一種方式:

string listtype = Console.ReadLine(); // say "System.Int32" 
Type t = Type.GetType(listtype); 
List<t> myIntegers = new List<>(); // does not compile, expects a "type" 
List<typeof(t)> myIntegers = new List<typeof(t)>(); // interesting - type must resolve at compile time? 

是否有此我可以C#中利用的方法?

+0

可能重複的[通行證實例化的System.Type爲類型參數爲通用類(http://stackoverflow.com/questions/266115/pass-an-instantiated-system -type-as-a-type-parameter-for-a-generic-class) – nawfal 2014-01-17 15:46:45

回答

22

你所尋找的是MakeGenericType

string elementTypeName = Console.ReadLine(); 
Type elementType = Type.GetType(elementTypeName); 
Type[] types = new Type[] { elementType }; 

Type listType = typeof(List<>); 
Type genericType = listType.MakeGenericType(types); 
IProxy proxy = (IProxy)Activator.CreateInstance(genericType); 

那麼你正在做的是越來越通用的「模板」類的類型定義,然後使用運行時駕駛各類建築類型的專業化。

4

這裏有一個問題:你真的需要創建一個具體的合同類型的渠道在你的具體情況?

由於您正在進行路由選擇,因此您可以簡單地處理泛型通道形狀。例如,如果你的路由單向唯一的消息,那麼你可以創建一個通道來發送消息出來是這樣的:

ChannelFactory<IOutputChannel> factory = new ChannelFactory<IOutputChannel>(binding, endpoint); 
IOutputChannel channel = factory.CreateChannel(); 
... 
channel.SendMessage(myRawMessage); 

如果您需要發送到雙向服務,只需要使用改爲IRequestChannel。

如果你正在做的路由,它是,在一般情況下,一個更容易只是普通的通道形狀處理(用一個通用的包羅萬象的服務合同外),只是確保你發送的消息擁有所有正確的標題和屬性。

+1

我有一個難題,標誌着我的問題的「答案」。就使用WCF而言,我能夠使用你提到的這種技術,它像一個魅力(謝謝你!)。我選擇了上述內容,因爲它在技術上回答了我所問的問題(即使這是更好的方法)。 – t3rse 2008-09-16 18:49:22

8

你應該看看這篇文章從Ayende:WCF, Mocking and IoC: Oh MY!。靠近底部的地方是一個名爲GetCreationDelegate的方法,它應該有所幫助。它基本上是:

string typeName = ...; 
Type proxyType = Type.GetType(typeName); 

Type type = typeof (ChannelFactory<>).MakeGenericType(proxyType); 

object target = Activator.CreateInstance(type); 

MethodInfo methodInfo = type.GetMethod("CreateChannel", new Type[] {}); 

return methodInfo.Invoke(target, new object[0]);