问:
打扰一下,请问
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());
{
Console.WriteLine(mbro.ToString());
}
}
}