A Short Description to MarshalByRefObjects Remote Object and Invocation Tips
A MarshalByRefObject is a remote object that runs on the server and accepts methods calls from the client. Its data is stored in the server’s memeory and its methods executed in the server’s AppDomain. Instead of passing around a variable that points to an object of this type, in reality only a pointer-like construct-called an ObjRef-is passed around.
MarshalByRefObject远程对象在服务端运行并接受来自Client端的方法调用。MarshalByRefObject远程对象的数据保存在Server端内存,并且也在Server端AppDomain内执行方法。仅仅一个类似指针的ObjRef(ObjRef is [Serializable])对象引用传递到Client端,ObjRef封装在Client端的Proxy object中。
ObjRef不同于C++语言的指针执行内存地址,而是包含网络地址(如TCP/IP地址和TCP端口)和Object ID,Server端通过Object ID来识别Client端正在调用的对象实例。
MarshalByRefObjects can be categorized into two groups: server-activated objects (SAOs) and client-activated objects (CAOs).
MarshalByRefObjects远程对象分为2组:服务端激活对象和客户端激活对象。这一点相信大家都了解。
1. Server-Activated Objects
服务端激活对象可以分为如下3种类型,不过Client端的调用代码都相同,使用Activator.GetObject()方法获取Remote Objects。
(1) Singleton Objects
Only one instance of a Singleton object can exist at any given time. When receiving a client’s request, the server checks its internal tables to see if an instance of this class already exists; if not, this object will be created an stored in the table.
Note Singletons have an associated lifetime as well, so be sure to override the standard lease time if you don't want your object to be destroyed after some minutes.
在任何时间,Server端仅存在一个Singleton对象实例(当然,有可能在Server端没有Singleton对象实例)。
For registering an object as a Singleton, you can use the following lines of code:
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(<YourClass>), "<URL>",
WellKnownObjectMode.Singleton);
Use Singletons when you want to share data or resources between clients.
(2) SingleCall Objects
For SingleCall objects the server will create a single object, execute the method, and destroy the object again. Objects of this kind can obviously not hold any state information.
每次接受来自Client端的请求,Server端创建一个新的SingleCall对象,执行调用的方法,然后释放对象。在Server端不保存对象状态信息。
SingleCall Objects are registered at the server using the following statement:
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(<YourClass>), "<URL>",
WellKnownObjectMode.SingleCall);
(3) Published Objects
When using either SingleCall or Singleton objects, the necessary instances will be created dynamically during a client's request. You publish a certain object instance that's been precreated on the server.
在没有Client端的请求过来之前,Published对象已经在Server端创建,这点和SingleCall/Singleton对象不同。并且Published对象可以通过constructor来初始化Class的成员变量。
In this case you can use RemotingServices.Marshal() to publish a given instance that behaves like a Singleton afterwards. The only difference is that the object has to already exist at the server before publication.
你需要使用RemotingServices.Marshal()来发行一个对象实例,如下代码所示。之后,Published对象和Singleton对象行为相似。
YourObject obj = new YourObject(<your params for constructor>);
RemotingServices.Marshal(obj,"YourUrl.soap");
2. Client-Activated Objects
A client-activated object (CAO) behaves mostly the same way as does a "normal" .NET object (or a COM object). When a creation request on the client is encountered (using Activator.CreateInstance() or the new operator), an activation message is sent to the server, where a remote object is created. On the client a proxy that holds the ObjRef to the server object is created like it is with SAOs.
CAO对象的行为与.Net对象(或COM对象)类似。当Client通过Activator.CreateInstance()或new来要求创建对象实例时,激活的消息就会发送到Server端,并创建客户端激活的对象实例。同时在Client端创建一个proxy,proxy拥有指向Server对象的ObjRef(对象引用)。
A client-activated object's lifetime is managed by the same lifetime service used by SAOs. CAOs are so-called stateful objects; an instance variable that has been set by the client can be retrieved again and will contain the correct value. These objects will store state information from one method call to the other. CAOs are explicitly created by the client, so they can have distinct constructors like normal .NET objects do.
CAO对象的生存期租约和SAO一样通过生存期租约服务(lifetime service)来管理。CAO对象是所谓的有状态对象。Client设置的实例变量可以再次被正确获取,这些对象将保存状态信息。CAO对象由Client显式创建,因此它们可以与正常的.Net对象一样有显式的构造函数。
(1) Direct/Transparent Creation 直接/透明创建对象
The .NET Remoting Framework can be configured to allow client-activated objects to be created like normal objects using the new operator. Unfortunately, this manner of creation has one serious drawback: you cannot use shared interfaces or base classes. This means that you either have to ship the compiled objects to your clients or use SoapSuds to extract the metadata. 注意其中提及的new关键字创建对象的缺点。
在Server端注册Client-Activated Object示例代码如下:
RemotingConfiguration.ApplicationName = "MyServer";
RemotingConfiguration.RegisterActivatedServiceType(
typeof(MyRemoteObject));
这里,不需要知道URL,但是需要设定RemotingConfiguration.ApplicationName来识别Remote Object。
Remote Object的URL为:http://<hostname>:<port>/<ApplicationName>
然后在Server对象存放的目录,通过 SoapSuds来提取对象的metadata(元数据):
soapsuds -ia:<server> -nowp -oa:<generated_metadata.dll>
<server> - 输入的Assembly Name,不要有.dll or .exe等后缀。
-nowp – 表示生成nonwrapped proxy,如果没有-nowp选项,则生成wrapped proxy。
另外,请注意:SoapSuds cannot extract the metadata for nondefault constructors。
Client通过引用上面创建的<generated_metadata.dll>,然后调用Client-Activated Objects如下:
//在Client端上的对象Type注册为可在Server上激活的类型
RemotingConfiguration.RegisterActivatedClientType(
typeof(MyRemoteObject),
"http://localhost:1234/MyServer");
// 调用new在Server端创建客户端激活的对象实例,Client端会创建一个proxy
MyRemoteObject obj1 = new MyRemoteObject();
(2) Using the Factory Design Pattern使用工厂设计模式来创建对象
我们知道SoapSuds不能够提取非缺省构造函数的元数据(metadata),因此当你的应用程序的设计依赖这一功能时,就可以考虑使用Factory Design Pattern来实现,Factory Design Pattern通过SAO提供一个的工厂方法来创建CAO对象示例。
这里简单描述一下步骤,详细代码可以查阅《Advanced .Net Remoting - C# Edition》Chapter 3。
- 定义Remote Object和Factory Object的共享接口或抽象类,编译.DLL。
- Server端引用上述DLL,并分别实现Remote Object和Factory Object。
- Factory Object提供一个工厂方法,用来根据Client的请求创建对应的Remote Object。
- 将Factory Object注册为Singleton的SAO对象。
- Client端获取Factory Object远程对象,并调用工厂方法获取对应的Remote Object。
Reference:
1. Ingo Rammer, Advanced .Net Remoting – C# Version