JGTM'2004 [MVP] 对MarshalByRefObject的讲解

问:
打扰一下,请问 MarshalByRefObject 中的 "Marshal" 应该怎样理解?
 
回复
按照 package 的意思理解 —— 当一个对象需要长途跋涉到另一个环境中时,需要将其 marshal 成一个可以传输的形态(比如在 .NET Remoting 中对象将被打包成一个 serializable ObjRef 实例 —— 这个 ByRef 就是指 ObjRef 这种形态);同理,当打包以后传输到目标地点,还要执行 unmarshal 的操作将其还原为内存中的对象。:)
 
问:
谢谢!
MarshalByRefObject 是不是可以这样理解:对被引用的对象进行 Marshal 。如果按照 package 的意思理解,那 package 的过程是怎样的?
 
MSDN 上这样讲:
MarshalByRefObject 是通过使用 代理 交换消息来跨应用程序域边界进行通讯的对象的基类 .
MarshalByRefObject 对象在本地应用程序域的边界内可直接访问。远程应用程序域中的应用程序首次访问 MarshalByRefObject 时,会向该远程应用程序传递 代理 。对该代理后面的调用将封送回驻留在本地应用程序域中的对象。
 
Marshal 中,上面所说的代理是什么?有什么用?
 
MSDN 上还讲到:
当跨应用程序域边界使用类型时,类型必须是从 MarshalByRefObject 继承的,而且由于对象的成员在创建它们的应用程序域之外无法使用,所以 不得复制对象的状态
 
既然对象的状态不能传递过去,那传递这个对象又有何意义?
第一次去理解 MarshalByRefObject ,有的问题可能提的比较肤浅,请您指点。
 
回复:
MarshalByRefObject 是所有可以在 AppDomain 边界外部访问的对象的基类,重心不是 marshal ,而是 object ,即 object that could be marshaled by reference ,也就是可以通过 Ref (实际上是 ObjRef 对象)的机制进行 封送 MSDN 中文版对 marshal 一词的翻译)的对象。封送的行为是由代理来做的,这里说的代理就是我文章中讲过的 .NET Remoting 的真实代理(即 RemotingProxy )。真实代理不是有一个 Invoke() 方法吗?当你透过对一个 MBRO 的透明代理访问该对象的方法时,透明代理将把基于堆栈的方法调用转换为方法调用消息( IMethodCallMessage )并转发给真实代理(在 Remoting 的场合中也即 RemotingProxy ),而 RemotingProxy 的任务就是把对象封送并连同方法调用消息一起转发给远程应用程序域;到达目的地以后的操作类似:远程应用程序域中的监听方当收到发来的方法调用消息时,先取出封送好的 ObjRef (这个对象里面保存着发来调用的那个对象!),将其结封( unmarshal )为本地的对象,并获得其透明代理,然后就可以把方法调用消息在转换回基于堆栈的调用发送给这个对象。
 
对象是在本地维护的,但是方法可以在远程调用。你比如说一个 web 应用程序,你是通过本地的浏览器远程访问这个应用程序,但是应用程序的状态不会由你的浏览器负责(所以你只是在访问这个应用程序提供给你的功能而已,你并没于拥有应用程序本身,包括其所有数据),你只是发送一个个的请求,服务器告诉你处理的结果。在 Remoting 中也是一样,当你获得一个远程对象的时候,你实际上只拥有对这个对象的一个远程引用,虽然你可以调用它的方法,但实际上这些操作都是发生在远程的(就是前面讲过的过程),你只是传入了一些参数,得到了一个结果,但对象的状态还是在远程维护的(换句话说,对象本身也就是对象的所有状态并没有被往返传递,传递的只是传入传出的参数 —— 当然,如果参数是一个 MBRO 的话,还是传递对象被封送的引用)。 
也许应该给你准备一个好理解的例子 …… 你就会豁然开朗了。:)
 
问:
我这样的理解对不对?
一般的对象与从 MarshalByRefObject 继承的对象区别是:
一般的对象只能在本地应用程序域之内被引用,而 MarshalByRefObject 对象可以跨越应用程序域边界被引用,甚至被远程引用。
 
回复
Exactly! 当对象跨出 AppDomain 边界的时候,实际上只是它的一个引用( ObjRef )。你比如说吧:
 
public class LocalObject
{
  public void CallRemoteObject(MarshalByRefObject mbro)
  {
    Console.WriteLine(mbro.ToString());
  }
}
 
当传入一个在本地创建的 mbro 对象时, ToString() 方法是直接发送给对象的;而当 mbro 是通过 Remoting 创建的远程对象的话,实际上它只是一个包含有已经 marshal 好的 ObjRef 的透明代理, ObjRef 里面有什么?对象实例的 URI !所以当你调用这个远程对象时,相当于向这个远程端口( tcp://remoteServer/xxxx.rem )发送方法调用消息而已。只不过透明代理隐藏了对象位置的概念,而 RemotingProxy 真实代理则是实际上处理远程方法调用和对象封送的中枢对象。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值