运行时可调用包装Runtime Callable Wrapper

公共语言运行时通过名为运行时可调用包装 (RCW) 的代理公开 COM 对象。The common language runtime exposes COM objects through a proxy called the runtime callable wrapper (RCW). 尽管 RCW 似乎是 .NET 客户端的普通对象,但它的主要功能是封送处理 .NET 客户端和 COM 对象之间的调用。Although the RCW appears to be an ordinary object to .NET clients, its primary function is to marshal calls between a .NET client and a COM object.

无论 COM 对象上有多少引用数目,运行时都只为每个 COM 对象创建一个 RCW。The runtime creates exactly one RCW for each COM object, regardless of the number of references that exist on that object. 运行时针对每个对象的每个进程维护一个 RCW。The runtime maintains a single RCW per process for each object. 如果在某个应用程序域或单元创建一个 RCW,然后传递一个其他应用程序域或单元的引用,则将使用第一个对象的代理。If you create an RCW in one application domain or apartment, and then pass a reference to another application domain or apartment, a proxy to the first object will be used. 如下图所示,任意数量的托管客户端都可拥有一个对公开 INew 和 INewer 接口的 COM 对象的引用。As the following illustration shows, any number of managed clients can hold a reference to the COM objects that expose INew and INewer interfaces.

下图显示了通过运行时可调用包装器访问 COM 对象的过程:The following image shows the process for accessing COM objects through the runtime callable wrapper:

通过 RCW 访问 COM 对象的过程。

借助从类型库派生而来的元数据,运行时创建正在调用的 COM 对象及其包装。Using metadata derived from a type library, the runtime creates both the COM object being called and a wrapper for that object. 每个 RCW 都在其包装的 COM 对象上维护一个接口指针的缓存,并且当不再需要 RCW 时释放 COM 对象上的引用。Each RCW maintains a cache of interface pointers on the COM object it wraps and releases its reference on the COM object when the RCW is no longer needed. 运行时在 RCW 上执行垃圾回收。The runtime performs garbage collection on the RCW.

在其他活动中,RCW 代表包装的对象封送托管代码和非托管代码间的数据。Among other activities, the RCW marshals data between managed and unmanaged code, on behalf of the wrapped object. 具体而言,每当在客户端和服务器之间传递数据的不同表示形式时,RCW 都向方法自变量和方法返回值提供封送处理。Specifically, the RCW provides marshaling for method arguments and method return values whenever the client and server have different representations of the data passed between them.

标准包装强制执行内置的封送处理规则。The standard wrapper enforces built-in marshaling rules. 例如,当 .NET 客户端将 String 类型作为自变量的一部分传递到非托管对象时,包装会将字符串转换为 BSTR 类型。For example, when a .NET client passes a String type as part of an argument to an unmanaged object, the wrapper converts the string to a BSTR type. 如果 COM 对象向它托管的调用方返回 BSTR,则调用方会收到 String。Should the COM object return a BSTR to its managed caller, the caller receives a String. 客户端和服务器都会发送和接收所熟悉的数据。Both the client and the server send and receive data that is familiar to them. 其他类型不需要转换。Other types require no conversion. 例如,标准包装始终无需转换类型即可在托管代码和非托管代码间传递 4 字节整数。For instance, a standard wrapper will always pass a 4-byte integer between managed and unmanaged code without converting the type.

封送处理所选接口Marshaling selected interfaces

运行时可调用包装器 (RCW) 的主要目的是隐藏托管和非托管编程模型之间的差异。The primary goal of the runtime callable wrapper (RCW) is to hide the differences between the managed and unmanaged programming models. 若要创建无缝转换,RCW 需使用选定的 COM 接口且不将其公开到 .NET 客户端,如下图所示。To create a seamless transition, the RCW consumes selected COM interfaces without exposing them to the .NET client, as shown in the following illustration.

下图显示了 COM 接口和运行时可调用包装器:The following image shows COM interfaces and the runtime callable wrapper:

带有接口的运行时可调用包装器的屏幕截图。

当创建为早期绑定对象时,RCW 为特定类型。When created as an early-bound object, the RCW is a specific type. 它可实现 COM 对象实现的接口,并可公开对象接口中的方法、属性和事件。It implements the interfaces that the COM object implements and exposes the methods, properties, and events from the object's interfaces. 图示中,RCW 公开 INew 接口,但使用“IUnknown”和“IDispatch”接口 。In the illustration, the RCW exposes the INew interface but consumes the IUnknown and IDispatch interfaces. 此外,RCW 向 .NET 客户端公开 INew 接口的所有成员。Further, the RCW exposes all members of the INew interface to the .NET client.

RCW 使用下表列出的接口,这些接口由其包装的对象公开。The RCW consumes the interfaces listed in the following table, which are exposed by the object it wraps.

接口Interface 描述Description
IDispatchIDispatch 用于通过反射后期绑定到 COM 对象。For late binding to COM objects through reflection.
IErrorInfoIErrorInfo 提供以下内容的文字描述:错误、错误源、帮助文件,帮助上下文以及定义错误的接口的 GUID(.NET 类始终为 GUID_NULL)。Provides a textual description of the error, its source, a Help file, Help context, and the GUID of the interface that defined the error (always GUID_NULL for .NET classes).
IProvideClassInfoIProvideClassInfo 如果正在包装的 COM 对象实现 IProvideClassInfo,RCW 会提取此接口中的类型信息以提供更佳的类型标识。If the COM object being wrapped implements IProvideClassInfo, the RCW extracts the type information from this interface to provide better type identity.
IUnknownIUnknown 针对对象标识、类型强制和生存期管理:For object identity, type coercion, and lifetime management:

- 对象标识- Object identity
运行时通过比较每个对象的 IUnknown 接口的值来区分 COM 对象。The runtime distinguishes between COM objects by comparing the value of the IUnknown interface for each object.
- 类型强制- Type coercion
RCW 识别由 QueryInterface 方法执行的动态类型发现。The RCW recognizes the dynamic type discovery performed by the QueryInterface method.
- 生存期管理- Lifetime management
借助 QueryInterface 方法,RCW 获取并保存对非托管对象的引用,直到运行时在包装器上执行会释放非托管对象的垃圾回收。Using the QueryInterface method, the RCW gets and holds a reference to an unmanaged object until the runtime performs garbage collection on the wrapper, which releases the unmanaged object.

RCW 选择性地使用下表中列出的接口,这些接口由其包装的对象公开。The RCW optionally consumes the interfaces listed in the following table, which are exposed by the object it wraps.

接口Interface 描述Description
IConnectionPointIConnectionPointContainerIConnectionPoint and IConnectionPointContainer RCW 对向基于委托的事件公开连接点事件样式的对象执行转换。The RCW converts objects that expose the connection-point event style to delegate-based events.
IDispatchEx(仅限 .NET Framework)IDispatchEx (.NET Framework Only) 如果类实现 IDispatchEx,则 RCW 实现 IExpando 。If the class implements IDispatchEx, the RCW implements IExpando. IDispatchEx 接口是 IDispatch 接口的扩展,与 IDispatch 不同,它可枚举、添加、删除和以区分大小的方式调用成员 。The IDispatchEx interface is an extension of the IDispatch interface that, unlike IDispatch, enables enumeration, addition, deletion, and case-sensitive calling of members.
IEnumVARIANTIEnumVARIANT 使支持枚举的 COM 类型可被视为集合。Enables COM types that support enumerations to be treated as collections.

请参阅See also