public interface IServerObject { Person GetPersonInfo(string name,string sex,int age); } public interface IServerObjFactory { IServerObject CreateInstance(); } public class ServerObject:MarshalByRefObject,IServerObject { public Person GetPersonInfo(string name,string sex,int age) { Person person = new Person(); person.Name = name; person.Sex = sex; person.Age = age; return person; } } public class ServerObjFactory:MarshalByRefObject,IServerObjFactory { public IServerObject CreateInstance() { return new ServerObject(); } } |
然後再客戶端的遠程對象中只提供工廠接口和原來的對象接口:
public interface IServerObject { Person GetPersonInfo(string name,string sex,int age); } public interface IServerObjFactory { IServerObject CreateInstance(); } |
我們用WellKnown激活模式註冊遠程對象,在服務器端:
//傳遞對象; RemotingConfiguration.RegisterWellKnownServiceType( typeof(ServerRemoteObject.ServerObjFactory), "ServiceMessage",WellKnownObjectMode.SingleCall); |
注意這裏註冊的不是ServerObject類對象,而是ServerObjFactory類對象。
客戶端:
ServerRemoteObject.IServerObjFactory serverFactory = (ServerRemoteObject.IServerObjFactory) Activator.GetObject( typeof(ServerRemoteObject.IServerObjFactory), "tcp://localhost:8080/ServiceMessage"); ServerRemoteObject.IServerObject serverObj = serverFactory.CreateInstance(); |
爲什麼說這是一種客戶端激活模式的模擬呢?從激活的方法來看,我們是使用了SingleCall模式來激活對象,但此時激活的並非我們要傳遞的遠程對象,而是工廠對象。如果客戶端要創建遠程對象,還應該通過工廠對象的CreateInstance()方法來獲得。而這個方法正是在客戶端調用的。因此它的實現方式就等同於客戶端激活模式。
b、利用替代類來取代遠程對象的元數據
實際上,我們可以用一個trick,來欺騙Remoting。這裏所說的替代類就是這個trick了。既然是提供服務,Remoting傳遞的遠程對象其實現的細節當然是放在服務器端。而要在客戶端放對象的副本,不過是因爲客戶端必須調用構造函數,而採取的無奈之舉。既然具體的實現是在服務器端,又爲了能在客戶端實例化,那麼在客戶端就實現這些好了。至於實現的細節,就不用管了。
如果遠程對象有方法,服務器端則提供方法實現,而客戶端就提供這個方法就OK了,至於裏面的實現,你可以是拋出一個異常,或者return 一個null值;如果方法返回void,那麼裏面可以是空。關鍵是這個客戶端類對象要有這個方法。這個方法的實現,其實和方法的聲明差不多,所以我說是一個trick。方法如是,構造函數也如此。
還是用代碼來說明這種“陰謀”,更直觀:
服務器端:
public class ServerObject:MarshalByRefObject { public ServerObject() {} public Person GetPersonInfo(string name,string sex,int age) { Person person = new Person(); person.Name = name; person.Sex = sex; person.Age = age; return person; } } |