天天看點

.NET Remoting程式開發入門篇(三)

四、用戶端

  用戶端主要做兩件事,一是注冊通道。這一點從圖一就可以看出,Remoting中伺服器端和用戶端都必須通過通道來傳遞消息,以獲得遠端對象。第二步則是獲得該遠端對象。

  1、注冊通道:

TcpChannel channel = new TcpChannel();

ChannelServices.RegisterChannel(channel);

  注意在用戶端執行個體化通道時,是調用的預設構造函數,即沒有傳遞端口号。事實上,這個端口号是缺一不可的,隻不過它的指定被放在後面作為了Uri的一部分。

  2、獲得遠端對象。

  與伺服器端相同,不同的激活模式決定了用戶端的實作方式也将不同。不過這個差別僅僅是WellKnown激活模式和用戶端激活模式之間的差別,而對于SingleTon和SingleCall模式,用戶端的實作完全相同。

   (1) WellKnown激活模式

  要獲得伺服器端的知名遠端對象,可通過Activator程序的GetObject()方法來獲得:

ServerRemoteObject.ServerObject serverObj = (ServerRemoteObject.ServerObject)Activator.GetObject(

typeof(ServerRemoteObject.ServerObject), "tcp://localhost:8080/ServiceMessage");

  首先以WellKnown模式激活,用戶端獲得對象的方法是使用GetObject()。其中參數第一個是遠端對象的類型。第二個參數就是伺服器端的uri。如果是http通道,自然是用http://localhost:8080/ServiceMessage了。因為我是用本地機,是以這裡是localhost,你可以用具體的伺服器IP位址來代替它。端口必須和伺服器端的端口一緻。後面則是伺服器定義的遠端對象服務名,即ApplicationName屬性的内容。

  (2) 用戶端激活模式

  如前所述,WellKnown模式在用戶端建立對象時,隻能調用預設的構造函數,上面的代碼就說明了這一點,因為GetObject()方法不能傳遞構造函數的參數。而用戶端激活模式則可以通過自定義的構造函數來建立遠端對象。

  用戶端激活模式有兩種方法:

  1) 調用RemotingConfiguration的靜态方法RegisterActivatedClientType()。這個方法傳回值為Void,它隻是将遠端對象注冊在用戶端而已。具體的執行個體化還需要調用對象類的構造函數。

RemotingConfiguration.RegisterActivatedClientType( typeof(ServerRemoteObject.ServerObject),

"tcp://localhost:8080/ServiceMessage");

ServerRemoteObject.ServerObject serverObj = new ServerRemoteObject.ServerObject();

  2) 調用程序Activator的CreateInstance()方法。這個方法将建立方法參數指定類型的類對象。它與前面的GetObject()不同的是,它要在用戶端調用構造函數,而GetObject()隻是獲得對象,而建立執行個體是在伺服器端完成的。CreateInstance()方法有很多個重載,我着重說一下其中常用的兩個。

   a、 public static object CreateInstance(Type type, object[] args, object[] activationAttributes);

  參數說明:

  type:要建立的對象的類型。

  args :與要調用構造函數的參數數量、順序和類型比對的參數數組。如果 args 為空數組或空引用(Visual Basic 中為 Nothing),則調用不帶任何參數的構造函數(預設構造函數)。

  activationAttributes :包含一個或多個可以參與激活的屬性的數組。

  這裡的參數args是一個object[]數組類型。它可以傳遞要建立對象的構造函數中的參數。從這裡其實可以得到一個結論:WellKnown激活模式所傳遞的遠端對象類,隻能使用預設的構造函數;而Activated模式則可以使用者自定義構造函數。activationAttributes參數在這個方法中通常用來傳遞伺服器的url。

  假設我們的遠端對象類ServerObject有個構造函數:

ServerObject(string pName,string pSex,int pAge)

{

 name = pName;

 sex = pSex;

 age = pAge;

}

  那麼實作的代碼是:

object[] attrs = {new UrlAttribute("tcp://localhost:8080/ServiceMessage")};

object[] objs = new object[3];

objs[0] = "wayfarer";

objs[1] = "male";

objs[2] = 28;

ServerRemoteObject.ServerObject = Activator.CreateInstance(

typeof(ServerRemoteObject.ServerObject),objs,attrs);

  可以看到,objs[]數組傳遞的就是構造函數的參數。

  b、public static ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttribute);

  參數說明:

  assemblyName :将在其中查找名為 typeName 的類型的程式集的名稱。如果 assemblyName 為空引用(Visual Basic 中為 Nothing),則搜尋正在執行的程式集。

  typeName:首選類型的名稱。

  activationAttributes :包含一個或多個可以參與激活的屬性的數組。

  參數說明一目了然。注意這個方法傳回值為ObjectHandle類型,是以代碼與前不同:

object[] attrs = {new UrlAttribute("tcp://localhost:8080/EchoMessage")};

ObjectHandle handle = Activator.CreateInstance("ServerRemoteObject",

"ServerRemoteObject.ServerObject",attrs);

ServerRemoteObject.ServerObject obj = (ServerRemoteObject.ServerObject)handle.Unwrap();

  這個方法實際上是調用的預設構造函數。ObjectHandle.Unwrap()方法是傳回被包裝的對象。

  說明:要使用UrlAttribute,還需要在命名空間中添加:using System.Runtime.Remoting.Activation;

繼續閱讀