通過上面的描述,基本上已經完成了一個最簡單的Remoting程序。這是一個標準的創建Remoting程序的方法,但在實際開發過程中,我們遇到的情況也許千奇百怪,如果只掌握一種所謂的“標準”,就妄想可以“一招鮮、吃遍天”,是不可能的。
1、註冊多個通道
在Remoting中,允許同時創建多個通道,即根據不同的端口創建不同的通道。但是,Remoting要求通道的名字必須不同,因爲它要用來作爲通道的唯一標識符。雖然IChannel有ChannelName屬性,但這個屬性是隻讀的。因此前面所述的創建通道的方法無法實現同時註冊多個通道的要求。
這個時候,我們必須用到System.Collection中的IDictionary接口:
註冊Tcp通道:
IDictionary tcpProp = new Hashtable(); tcpProp["name"] = "tcp9090"; tcpProp["port"] = 9090; IChannel channel = new TcpChannel(tcpProp, new BinaryClientFormatterSinkProvider(), new BinaryServerFormatterSinkProvider()); ChannelServices.RegisterChannel(channel); |
註冊Http通道:
IDictionary httpProp = new Hashtable(); httpProp["name"] = "http8080"; httpProp["port"] = 8080; IChannel channel = new HttpChannel(httpProp, new SoapClientFormatterSinkProvider(), new SoapServerFormatterSinkProvider()); ChannelServices.RegisterChannel(channel); |
在name屬性中,定義不同的通道名稱就可以了。
2、遠程對象元數據相關性
由於服務器端和客戶端都要用到遠程對象,通常的方式是生成兩份完全相同的對象Dll,分別添加引用。不過爲了代碼的安全性,且降低客戶端對遠程對象元數據的相關性,我們有必要對這種方式進行改動。即在服務器端實現遠程對象,而在客戶端則刪除這些實現的元數據。
由於激活模式的不同,在客戶端創建對象的方法也不同,所以要分離元數據的相關性,也應分爲兩種情況。
(1) WellKnown激活模式:
通過接口來實現。在服務器端,提供接口和具體類的實現,而在客戶端僅提供接口:
public interface IServerObject { Person GetPersonInfo(string name,string sex,int age); } public class ServerObject:MarshalByRefObject,IServerObject { ......} |
注意:兩邊生成該對象程序集的名字必須相同,嚴格地說,是命名空間的名字必須相同。
(2) 客戶端激活模式:
如前所述,對於客戶端激活模式,不管是使用靜態方法,還是使用CreateInstance()方法,都必須在客戶端調用構造函數實例化對象。所以,在客戶端我們提供的遠程對象,就不能只提供接口,而沒有類的實現。實際上,要做到與遠程對象元數據的分離,可以由兩種方法供選擇:
a、利用WellKnown激活模式模擬客戶端激活模式:
方法是利用設計模式中的“抽象工廠”,下面的類圖表描述了總體解決方案: