天天看點

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

用戶端:

public class ServerObject:MarshalByRefObject

{

 public ServerObj()

 {

  throw new System.NotImplementedException();

 }

 public Person GetPersonInfo(string name,string sex,int age)

 {

  throw new System.NotImplementedException();

 }

}

  比較用戶端和伺服器端,用戶端的方法GetPersonInfo(),沒有具體的實作細節,隻是抛出了一個異常。或者直接寫上語句return null,照樣OK。我們稱用戶端的這個類為遠端對象的替代類。

  3、利用配置檔案實作

  前面所述的方法,于伺服器uri、端口、以及激活模式的設定是用代碼來完成的。其實我們也可以用配置檔案來設定。這樣做有個好處,因為這個配置檔案是Xml文檔。如果需要改變端口或其他,我們就不需要修改程式,并重新編譯,而是隻需要改變這個配置檔案即可。 (1) 伺服器端的配置檔案:

<configuration>

<system.runtime.remoting>

<application name="ServerRemoting">

<service>

<wellknown mode="Singleton" type="ServerRemoteObject.ServerObject" objectUri="ServiceMessage"/>

</service>

<channels>

<channel ref="tcp" port="8080"/>

</channels>

</application>

</system.runtime.remoting>

</configuration>

  如果是用戶端激活模式,則把wellknown改為activated,同時删除mode屬性。

  把該配置檔案放到伺服器程式的應用程式檔案夾中,命名為ServerRemoting.config。那麼前面的伺服器端程式直接用這條語句即可:

RemotingConfiguration.Configure("ServerRemoting.config");

  (2) 用戶端配置檔案

  如果是用戶端激活模式,修改和上面一樣。調用也是使用RemotingConfiguration.Configure()方法來調用存儲在用戶端的配置檔案。

  配置檔案還可以放在machine.config中。如果用戶端程式是web應用程式,則可以放在web.config中。

  4、啟動/關閉指定遠端對象

  Remoting中沒有提供類似UnregisterWellKnownServiceType()的方法,也即是說,一旦通過注冊了遠端對象,如果沒有關閉通道的話,該對象就一直存在于通道中。隻要用戶端激活該對象,就會建立對象執行個體。如果Remoting傳送的隻有一個遠端對象,這不存在問題,關閉通道就可以了。如果傳送多個遠端對象呢?要關閉指定的遠端對象應該怎麼做?關閉之後又需要啟動又該如何?

  我們注意到在Remoting中提供了Marshal()和Disconnect()方法,答案就在這裡。Marshal()方法是将MarshalByRefObject類對象轉化為ObjRef類對象,這個對象是存儲生成代理以與遠端對象通訊所需的所有相關資訊。這樣就可以将該執行個體序列化以便在應用程式域之間以及通過網絡進行傳輸,用戶端就可以調用了。而Disconnect()方法則将具體的執行個體對象從通道中斷開。

  方法如下:

  首先注冊通道:

TcpChannel channel = new TcpChannel(8080);

ChannelServices.RegisterChannel(channel);

  接着啟動服務:

  先在伺服器端執行個體化遠端對象。

ServerObject obj = new ServerObject();

然後,注冊該對象。注意這裡不用RemotingConfiguration.RegisterWellKnownServiceType(),而是使用RemotingServices.Marshal():

ObjRef objrefWellKnown = RemotingServices.Marshal(obj, "ServiceMessage");

  如果要登出對象,則:

RemotingServices.Disconnect(obj);

  要注意,這裡Disconnect的類對象必須是前面執行個體化的對象。正因為此,我們可以根據需要建立指定的遠端對象,而關閉時,則Disconnect之前執行個體化的對象。

  至于用戶端的調用,和前面WellKnown模式的方法相同,仍然是通過Activator.GetObject()來獲得。但從實作代碼來看,我們會注意到一個問題,由于伺服器端是顯式的執行個體化了遠端對象,是以不管用戶端有多少,是否相同,它們調用的都是同一個遠端對象。是以我們将這個方法稱為模拟的SingleTon模式。

  用戶端激活模式

  我們也可以通過Marshal()和Disconnect()來模拟用戶端激活模式。首先我們來回顧“遠端對象中繼資料相關性”一節,在這一節中,我說到采用設計模式的“抽象工廠”來建立對象執行個體,以此用SingleCall模式來模拟用戶端激活模式。在仔細想想前面的模拟的SingleTon模式。是不是答案就将呼之欲出呢?

  在“模拟的SingleTon”模式中,我們是将具體的遠端對象執行個體進行Marshal,以此讓用戶端獲得該對象的引用資訊。那麼我們換一種思路,當我們用抽象工廠提供接口,工廠類實作建立遠端對象的方法。然後我們在伺服器端建立工廠類執行個體。再将這個工廠類執行個體進行Marshal。而用戶端擷取對象時,不是擷取具體的遠端對象,而是擷取具體的工廠類對象。然後再調用CreateInstance()方法來建立具體的遠端對象執行個體。此時,對于多個用戶端而言,調用的是同一個工廠類對象;然而遠端對象是在各個用戶端自己建立的,是以對于遠端對象而言,則是由用戶端激活,建立的是不同對象了。

  當我們要啟動/關閉指定對象時,隻需要用Disconnet()方法來登出工廠類對象就可以了。

  六、小結

  

  Microsoft.Net Remoting真可以說是博大精深。整個Remoting的内容不是我這一篇小文所能盡述的,更不是我這個Remoting的初學者所能掌握的。王國維在《人間詞話》一書中寫到:古今之成大事業大學問者,必經過三種境界。“昨夜西風凋碧樹,獨上高樓,望盡天涯路。”此第一境界也。“衣帶漸寬終不悔,為伊消得人憔悴。”此第二境界也。“衆裡尋他千百度,蓦然回首,那人卻在燈火闌珊處。”此第三境界也。如以此來形容我對Remoting的學習,還處于“獨上高樓,望盡天涯路”的時候,真可以說還未曾登堂入室。

  或許需得“衣帶漸寬”,學得Remoting“終不悔”,方才可以“蓦然回首”吧。

繼續閱讀