可远程处理和不可远程处理的对象
请记住,在一个应用程序域中创建并因而特定于该域的对象可以直接从该域中调用,但如果要从该域中调用在其他域中创建的对象,就必须先进行一些设置,这一点非常重要。并非所有类型的对象都可以跨域边界进行有效地发布和使用;因此,必须根据应用程序的要求来决定要发布哪种对象。为了开发分布式应用程序,有两类对象可供选择:不可远程处理的对象和可远程处理的对象。
不可远程处理的对象
有些对象不能离开它们的应用程序域;这些对象未声明序列化方法,因而永远得不到封送处理。这些不可远程处理的对象专门在创建它们的应用程序域中使用,并始终直接从该应用程序域进行访问。.NET Framework 类库中的大多数基类都属于不可远程处理的对象。不可远程处理的对象不能在其他应用程序域中进行复制或表示。这些对象只能从它们的原始应用程序域进行访问。
可远程处理的对象
可远程处理的对象能够从其应用程序域或使用代理的上下文之外进行访问,您也可以复制它们并在其应用程序域或上下文之外传递其副本;这意味着,有些可远程处理的对象将通过引用进行传递,有些则将通过值传递。
可远程处理的对象是能够在大范围分布式环境中正常运行的对象。它们主要有两种类型:
按值封送对象,这种对象将从应用程序域中进行复制和传递。
引用封送对象,将为这种对象创建代理,而客户端则使用代理远程访问这些对象。
按值封送对象
按值封送 (MBV) 对象声明其序列化规则(通过实现 ISerializable 来实现其自己的序列化,或者通过用 SerializableAttribute 标记以指示系统自动序列化该对象),但不扩展 MarshalByRefObject。远程处理系统会创建这些对象的完整副本,并将该副本传递给调用应用程序域。当该副本到达调用方的应用程序域中时,对该副本的调用将直接转到该副本。另外,以参数形式传递的 MBV 对象还将按值传递。除了声明 SerializableAttribute 属性或实现 ISerializable 外,您无需执行任何操作即可跨应用程序或上下文边界按值传递类的实例。
注意: |
---|
从 .NET Framework 1.1 版开始,远程处理基础结构不会自动在服务器上反序列化某些类型。如果应用程序尝试传递的类型未被自动序列化,则必须将服务器反序列化级别设置为 Full,才能使服务器反序列化并使用 MBV 对象。有关更多信息,请参见 .NET 远程处理中的自动反序列化。 |
如果将对象的完整状态以及任何可执行功能移到目标应用程序域能够提高性能或方便处理,请使用 MBV 对象。频繁在网络、进程和应用程序域边界之间来回往返既耗时,又占用资源。在很多情况下,使用 MBV 对象可以减少这些往来次数。MBV 对象也可以直接在其原始应用程序域中使用。在这种情况下,由于不进行封送处理,即不用创建任何副本,因而访问起来十分有效。
应使用 SerializableAttribute 创建按值封送类型,除非需要扩展已实现 ISerializable 的类。在此情况下,必须为该类型实现 ISerializable。
远程处理系统大量使用可序列化对象。对其他应用程序域中的对象的引用(在远程处理系统中由 ObjRef 类表示)本身即可进行序列化;必须能够完全复制该对象并将副本发送至客户端。另外,传输数据的对象通常是可序列化对象。例如,DataSet 扩展 MarshalByValueComponent,后者实现 ISerializable。
远程处理用户定义的异常
系统定义的异常都属于按值封送类型(它们实现 ISerializable 接口),当远程对象引发这类异常时,如果远程处理配置允许,这类异常将被自动复制给调用方。从 .NET Framework 1.1 版开始,必须将 <customErrors> 元素设置为 off,才能使这些异常流向调用方。
有关如何创建可由远程对象引发并由远程调用方捕获的异常类型的更多信息,请参见如何:创建可由远程对象引发的异常类型
引用封送对象
引用封送 (MBR) 对象是至少扩展了 System.MarshalByRefObject 的可远程处理对象。根据已声明的激活类型,当客户端在其自己的应用程序域中创建 MBR 对象的实例后,.NET 远程处理结构将创建表示该 MBR 对象的代理,并向调用方返回对该代理的引用。随后,客户端将调用该代理。.NET 远程处理会将这些调用封送给远程对象所在的应用程序域,从而实现迭代调用。
注意: |
---|
如果客户端与 MBR 对象位于同一应用程序域中,基础结构将向客户端返回对 MBR 对象的直接引用,从而避免了封送处理的开销。 |
如果 System.MarshalByRefObject 是以参数形式传递的,则当调用抵达后,它将变为另一个应用程序域中的代理。MBR 返回值与 out 参数的工作方式相同。
注意: |
---|
从 .NET Framework 1.1 版开始,.NET 远程处理基础结构不会自动在服务器上反序列化某些类型。例如,若要获取对以参数形式传递的 MBR 对象的支持,必须将服务器的反序列化级别设置为 Full,才能使服务器反序列化并使用 MBR 参数。有关更多信息,请参见 .NET 远程处理中的自动反序列化。 |
如果对象的状态和任何可执行功能均应保留在创建它的应用程序域内,则应使用 MBR 对象。例如,如果一个对象有内部字段是操作系统句柄,该对象就应扩展 System.MarshalByRefObject,因为操作系统句柄在其他应用程序域、进程或计算机中没有意义。有时,对象还可能超过允许的大小限制;在可靠的服务器上,该对象也许还能正常工作,但如果通过网线将其发送到 33.6 KBps 的调制解调器,该对象将无法正常工作。
上下文绑定对象
上下文绑定对象是继承自 System.ContextBoundObject(本身继承自 System.MarshalByRefObject)的 MBR 对象。您可以将上下文视为应用程序域的一个分支,在执行的过程中,它可为驻留在其中的对象提供丰富的环境。例如,上下文可以保证对象没有同时被多个线程访问。每个应用程序域都有一个默认上下文。大多数托管代码在创建对象后,都会从同一应用程序域中使用该域的默认上下文直接调用其成员,从而不会出现与上下文相关的问题。所有继承自 System.ContextBoundObject 的类型对其他上下文(同一个域或其他域中)都将公开为代理。
例如,假设某方法的类型是事务的一部分,因此该方法将由特定于其创建上下文的规则绑定。该类型应继承自 System.ContextBoundObject,才能从对象自身的上下文中访问该对象,而系统也才能强制实施与该对象及其方法关联的事务相关的规则。如果从同一应用程序域中的另一个上下文中调用 System.ContextBoundObject,将为调用方创建代理,但上下文之间的通信将不通过信道系统,这样便提高了调用效率。
由于跨越每个边界都要消耗处理时间,因此在决定服务器应属于何种可远程处理的对象之前,应确定对象必须跨越哪些边界。特定于某个上下文的对象只能直接从该上下文中访问。对于特定于某个应用程序域的对象,也适用同样的规则。无论要远程处理上面哪类对象,远程处理系统都必须成功跨越上下文边界和/或应用程序边界,才能从服务器对象特定的任何边界内调用该对象。如果无需上下文检查即可调用对象,则不应让远程类型扩展 System.ContextBoundObject;使用 System.MarshalByRefObject 效果会更好。如果需要执行上下文检查,则应当扩展 System.ContextBoundObject,但您必须明白,必须跨越附加的边界才能调用该对象。
发布范围
不同的远程处理系统采用不同的方式来确定可以远程使用的成员和成员类型。.NET 远程处理会将对象向其他应用程序域公开为局部对象,但存在以下几种例外:
静态成员。
静态字段和方法永远不进行远程处理,字段是直接通过内存访问的。即,.NET 远程处理始终会处理某种形式的实例成员。
实例字段和访问器。
对于实例字段和访问器方法,系统会在运行时插入检查,以确定对象是否为代理。如果不是代理,将直接访问字段。否则,将由代理为调用方提供访问器。
私有方法。
私有方法不能远程处理。您不能包装委托并将其远程传递给私有方法。
委托。
委托是按值封送对象。委托中的对象可以是任何类型的可远程处理对象 - 可序列化对象、MarshalByRefObject 对象或 ContextBoundObject 对象。唯一的例外是,接口方法的委托不能成功进行远程处理。该委托包装接口方法的实现,这要求服务器能获取客户端的类型信息。
对象的重写方法。
出于性能方面的考虑,对象的虚拟方法始终在调用它们的应用程序域中本地执行。对于下列任何方法,当它们在远程对象上被重写后,对它们的调用都只转到该远程对象:
Equals
此虚拟方法在被重写后将从远程执行。
GetHashCode
此方法在本地执行。
ToString
此虚拟方法在被重写后将从远程执行。
Equals(静态版本)
此方法在本地执行。
MemberwiseClone
此方法在本地执行。
请参见
任务
其他资源
.NET Framework 远程处理概述
使对象可远程处理
版权所有 (C) 2007 Microsoft Corporation。保留所有权利。