ICustomMarshaler ICustomMarshaler ICustomMarshaler ICustomMarshaler Interface

定义

提供用于处理方法调用的自定义包装器。Provides custom wrappers for handling method calls.

public interface class ICustomMarshaler
[System.Runtime.InteropServices.ComVisible(true)]
public interface ICustomMarshaler
type ICustomMarshaler = interface
Public Interface ICustomMarshaler
派生
属性

注解

封送处理程序提供的旧功能和新的接口之间的桥梁。A marshaler provides a bridge between the functionality of old and new interfaces. 自定义封送处理提供以下优势:Custom marshaling provides the following benefits:

  • 这样,客户端应用程序已设计为使用旧接口也适用于实现的新接口的服务器。It enables client applications that were designed to work with an old interface to also work with servers that implement a new interface.

  • 这样,客户端应用程序构建为的新界面可用于实现旧接口的服务器。It enables client applications built to work with a new interface to work with servers that implement an old interface.

如果您有一个接口,这就带来了不同的封送处理行为或以其他方式公开到组件对象模型 (COM),您可以设计而不是使用互操作封送处理程序自定义封送处理程序。If you have an interface that introduces different marshaling behavior or that is exposed to the Component Object Model (COM) in a different way, you can design a custom marshaler instead of using the interop marshaler. 通过使用自定义封送处理程序,可以尽量减少新.NET Framework 组件和现有 COM 组件之间的区别。By using a custom marshaler, you can minimize the distinction between new .NET Framework components and existing COM components.

例如,假设您正在开发名为的托管的界面INewFor example, suppose that you are developing a managed interface called INew. 当此接口通过标准的 COM 可调用包装 (CCW) 公开到 COM 时,它与托管接口具有相同的方法,并使用互操作封送处理程序中内置的封送处理规则。When this interface is exposed to COM through a standard COM callable wrapper (CCW), it has the same methods as the managed interface and uses the marshaling rules built into the interop marshaler. 现在,假设已知的 COM 接口调用IOld已经提供了相同的功能INew接口。Now suppose that a well-known COM interface called IOld already provides the same functionality as the INew interface. 可以通过自定义封送处理程序,提供的非托管的实现IOld,只需将调用委托给的托管实现INew接口。By designing a custom marshaler, you can provide an unmanaged implementation of IOld that simply delegates the calls to the managed implementation of the INew interface. 因此,自定义封送处理程序的托管和非托管接口之间起到桥梁作用。Therefore, the custom marshaler acts as a bridge between the managed and unmanaged interfaces.

备注

当从托管代码调用到非托管代码仅支持调度的接口上时,不会调用自定义封。Custom marshalers are not invoked when calling from managed code to unmanaged code on a dispatch-only interface.

定义封送处理类型Defining the Marshaling Type

您可以构建自定义封送处理程序之前,必须定义将被封送托管和非托管接口。Before you can build a custom marshaler, you must define the managed and unmanaged interfaces that will be marshaled. 通常,这些接口执行相同的功能,但以不同的方式公开给托管和非托管对象。These interfaces commonly perform the same function but are exposed differently to managed and unmanaged objects.

托管的编译器会生成元数据,从托管的接口,生成的接口看上去像任何其他托管接口。A managed compiler produces a managed interface from metadata, and the resulting interface looks like any other managed interface. 下面的示例演示一个典型的接口。The following example shows a typical interface.

public interface class INew
{
    void NewMethod();
};
public interface INew
{
    void NewMethod();
}
Public Interface INew
    Sub NewMethod()
End Interface

定义在接口定义语言 (IDL) 的非托管的类型,并使用 Microsoft 接口定义语言 (MIDL) 编译器进行编译。You define the unmanaged type in Interface Definition Language (IDL) and compile it with the Microsoft Interface Definition Language (MIDL) compiler. Library 语句中定义该接口,并将其分配具有通用唯一标识符 (UUID) 属性的接口 ID,如以下示例所示。You define the interface within a library statement and assign it an interface ID with the universal unique identifier (UUID) attribute, as the following example demonstrates.

 [uuid(9B2BAADA-0705-11D3-A0CD-00C04FA35826)]  
library OldLib {  
     [uuid(9B2BAADD-0705-11D3-A0CD-00C04FA35826)]  
     interface IOld : IUnknown  
         HRESULT OldMethod();  
}  

MIDL 编译器会生成多个输出文件。The MIDL compiler produces several output files. 如果在 Old.idl 定义接口,则定义的输出文件 Old_i.cconst变量具有接口标识符 (IID) 的接口,如以下示例所示。If the interface is defined in Old.idl, the output file Old_i.c defines a const variable with the interface identifier (IID) of the interface, as the following example demonstrates.

const IID IID_IOld = {0x9B2BAADD,0x0705,0x11D3,{0xA0,0xCD,0x00,0xC0,0x4F,0xA3,0x58,0x26}};  

Old.h 文件也会由 MIDL 生成。The Old.h file is also produced by MIDL. 它包含可以在 c + + 源代码中包含的接口的 c + + 定义。It contains a C++ definition of the interface that can be included in your C++ source code.

实现 ICustomMarshaler 接口Implementing the ICustomMarshaler Interface

在自定义封送处理程序必须实现ICustomMarshaler接口,以提供给运行时相应的包装。Your custom marshaler must implement the ICustomMarshaler interface to provide the appropriate wrappers to the runtime.

下面的 C# 代码显示所有自定义封必须实现的基接口。The following C# code displays the base interface that must be implemented by all custom marshalers.

public interface class ICustomMarshaler
{
     Object^ MarshalNativeToManaged( IntPtr^ pNativeData );
     IntPtr^ MarshalManagedToNative( Object^ ManagedObj );
     void CleanUpNativeData( IntPtr^ pNativeData );
     void CleanUpManagedData( Object^ ManagedObj );
     int GetNativeDataSize();
};
public interface ICustomMarshaler
{
     Object MarshalNativeToManaged( IntPtr pNativeData );
     IntPtr MarshalManagedToNative( Object ManagedObj );
     void CleanUpNativeData( IntPtr pNativeData );
     void CleanUpManagedData( Object ManagedObj );
     int GetNativeDataSize();
}
Public Interface ICustomMarshaler
     Function MarshalNativeToManaged( pNativeData As IntPtr ) As Object
     Function MarshalManagedToNative( ManagedObj As Object ) As IntPtr
     Sub CleanUpNativeData( pNativeData As IntPtr )
     Sub CleanUpManagedData( ManagedObj As Object )
     Function GetNativeDataSize() As Integer
End Interface

ICustomMarshaler接口包含提供转换支持、 清理支持和有关的数据要封送处理信息的方法。The ICustomMarshaler interface includes methods that provide conversion support, cleanup support, and information about the data to be marshaled.

操作类型Type of operation ICustomMarshaler 方法ICustomMarshaler method 描述Description
转换 (从本机到托管代码)Conversion (from native to managed code) MarshalNativeToManaged 将指向本机数据的封送到托管对象。Marshals a pointer to native data into a managed object. 此方法返回可封送作为参数传递的非托管的接口的自定义运行时可调用包装 (RCW)。This method returns a custom runtime callable wrapper (RCW) that can marshal the unmanaged interface that is passed as an argument. 封送处理程序应返回该类型的自定义 rcw 实例。The marshaler should return an instance of the custom RCW for that type.
转换 (从托管到本机代码)Conversion (from managed to native code) MarshalManagedToNative 将托管的对象封送到本机数据的指针。Marshals a managed object into a pointer to native data. 此方法返回的自定义 COM 可调用包装 (CCW) 可封送托管的接口,作为参数传递。This method returns a custom COM callable wrapper (CCW) that can marshal the managed interface that is passed as an argument. 封送处理程序应返回该类型的自定义的 CCW 的实例。The marshaler should return an instance of the custom CCW for that type.
清理 (的本机代码)Cleanup (of native code) CleanUpNativeData 使封送处理程序以进行本机数据 (CCW) 返回的清除MarshalManagedToNative方法。Enables the marshaler to clean up the native data (the CCW) that is returned by the MarshalManagedToNative method.
清理 (托管代码)Cleanup (of managed code) CleanUpManagedData 使封送处理程序以清理托管数据 (RCW) 返回的MarshalNativeToManaged方法。Enables the marshaler to clean up the managed data (the RCW) that is returned by the MarshalNativeToManaged method.
(有关本机代码) 的信息Information (about native code) GetNativeDataSize 返回要封送处理的非托管数据的大小。Returns the size of the unmanaged data to be marshaled.

转换Conversion

ICustomMarshaler.MarshalNativeToManaged

将指向本机数据的封送到托管对象。Marshals a pointer to native data into a managed object. 此方法返回可封送作为参数传递的非托管的接口的自定义运行时可调用包装 (RCW)。This method returns a custom runtime callable wrapper (RCW) that can marshal the unmanaged interface that is passed as an argument. 封送处理程序应返回该类型的自定义 rcw 实例。The marshaler should return an instance of the custom RCW for that type.

ICustomMarshaler.MarshalManagedToNative

将托管的对象封送到本机数据的指针。Marshals a managed object into a pointer to native data. 此方法返回的自定义 COM 可调用包装 (CCW) 可封送托管的接口,作为参数传递。This method returns a custom COM callable wrapper (CCW) that can marshal the managed interface that is passed as an argument. 封送处理程序应返回该类型的自定义的 CCW 的实例。The marshaler should return an instance of the custom CCW for that type.

清理Cleanup

ICustomMarshaler.CleanUpNativeData

使封送处理程序以进行本机数据 (CCW) 返回的清除MarshalManagedToNative方法。Enables the marshaler to clean up the native data (the CCW) that is returned by the MarshalManagedToNative method.

ICustomMarshaler.CleanUpManagedData

使封送处理程序以清理托管数据 (RCW) 返回的MarshalNativeToManaged方法。Enables the marshaler to clean up the managed data (the RCW) that is returned by the MarshalNativeToManaged method.

大小信息Size Information

ICustomMarshaler.GetNativeDataSize

返回要封送处理的非托管数据的大小。Returns the size of the unmanaged data to be marshaled.

实现 GetInstance 方法Implementing the GetInstance Method

除了实现ICustomMarshaler接口,必须实现自定义封static方法调用GetInstance接受String作为参数和返回类型为ICustomMarshalerIn addition to implementing the ICustomMarshaler interface, custom marshalers must implement a static method called GetInstance that accepts a String as a parameter and has a return type of ICustomMarshaler. static方法由公共语言运行时的 COM 互操作层,若要实例化自定义封送处理程序的实例。This static method is called by the common language runtime's COM interop layer to instantiate an instance of the custom marshaler. 传递给字符串GetInstance是该方法可用于自定义返回自定义封送处理程序的 cookie。The string that is passed to GetInstance is a cookie that the method can use to customize the returned custom marshaler.

static ICustomMarshaler *GetInstance(String *pstrCookie);  

应用 MarshalAsAttributeApplying MarshalAsAttribute

若要使用自定义封送处理程序,必须应用MarshalAsAttribute属性的参数或被封送处理的字段。To use a custom marshaler, you must apply the MarshalAsAttribute attribute to the parameter or field that is being marshaled.

你还必须传递UnmanagedType.CustomMarshaler枚举值MarshalAsAttribute构造函数。You must also pass the UnmanagedType.CustomMarshaler enumeration value to the MarshalAsAttribute constructor. 此外,还必须指定MarshalType字段的命名参数,则以下项之一:In addition, you must specify the MarshalType field with one of the following named parameters:

  • MarshalType (必需):自定义封送处理程序程序集限定名称。MarshalType (required): The assembly-qualified name of the custom marshaler. 该名称应包含的命名空间和类的自定义封送处理程序。The name should include the namespace and class of the custom marshaler. 如果在中使用的程序集中未定义自定义封送处理程序,必须指定在其中定义的程序集的名称。If the custom marshaler is not defined in the assembly it is used in, you must specify the name of the assembly in which it is defined.

    备注

    可以使用MarshalTypeRef字段,而不是MarshalType字段。You can use the MarshalTypeRef field instead of the MarshalType field. MarshalTypeRef 采用更方便地指定的类型。MarshalTypeRef takes a type that is easier to specify.

  • MarshalCookie (可选):一个传递给自定义封送处理程序的 cookie。MarshalCookie (optional): A cookie that is passed to the custom marshaler. 可以使用 cookie 向封送处理程序提供的其他信息。You can use the cookie to provide additional information to the marshaler. 例如,如果同一封送处理程序用于提供多个包装,cookie 标识特定的包装器。For example, if the same marshaler is used to provide a number of wrappers, the cookie identifies a specific wrapper. 将 cookie 传递给GetInstance封送处理程序方法。The cookie is passed to the GetInstance method of the marshaler.

MarshalAsAttribute属性标识自定义封送处理程序,使其可以激活适当的包装。The MarshalAsAttribute attribute identifies the custom marshaler so it can activate the appropriate wrapper. 公共语言运行时的互操作服务然后会检查该属性,并创建要封送处理的参数 (参数或字段) 需求的自定义封送处理程序第一次。The common language runtime's interop service then examines the attribute and creates the custom marshaler the first time the argument (parameter or field) needs to be marshaled.

然后,运行时调用MarshalNativeToManagedMarshalManagedToNative上激活正确的包装器来处理在调用自定义封送处理程序的方法。The runtime then calls the MarshalNativeToManaged and MarshalManagedToNative methods on the custom marshaler to activate the correct wrapper to handle the call.

使用自定义封送处理程序Using a Custom Marshaler

自定义封送处理程序完成后,您可以将其用作自定义包装程序特定的类型。When the custom marshaler is complete, you can use it as a custom wrapper for a particular type. 下面的示例演示的定义IUserData托管的接口:The following example shows the definition of the IUserData managed interface:

public interface class IUserData
{
    void DoSomeStuff(INew^ pINew);
};
interface IUserData
{
    void DoSomeStuff(INew pINew);
}
Public Interface IUserData
    Sub DoSomeStuff(pINew As INew)
End Interface

在以下示例中,IUserData接口使用NewOldMarshaler自定义封送处理程序,使非托管客户端应用程序传递IOld接口DoSomeStuff方法。In the following example, the IUserData interface uses the NewOldMarshaler custom marshaler to enable unmanaged client applications to pass an IOld interface to the DoSomeStuff method. 托管的说明DoSomeStuff方法采用INew接口,而在前面的示例所示的非托管的版本DoSomeStuff采用IOld接口指针,如下面的示例中所示。The managed description of the DoSomeStuff method takes an INew interface, as shown in the previous example, whereas the unmanaged version of DoSomeStuff takes an IOld interface pointer, as shown in the following example.

[uuid(9B2BAADA-0705-11D3-A0CD-00C04FA35826)]  
library UserLib {  
     [uuid(9B2BABCD-0705-11D3-A0CD-00C04FA35826)]  
     interface IUserData : IUnknown  
         HRESULT DoSomeStuff(IUnknown* pIOld);  
}  

通过将导出的托管的定义生成的类型库IUserData而不是标准定义此示例中所示的非托管定义。The type library that is generated by exporting the managed definition of IUserData yields the unmanaged definition shown in this example instead of the standard definition. MarshalAsAttribute特性应用于INew参数中的托管定义DoSomeStuff方法指示该参数使用了自定义封送处理程序,如以下示例所示。The MarshalAsAttribute attribute applied to the INew argument in the managed definition of the DoSomeStuff method indicates that the argument uses a custom marshaler, as the following example shows.

using namespace System::Runtime::InteropServices;
using System.Runtime.InteropServices;
Imports System.Runtime.InteropServices
public interface class IUserData
{
    void DoSomeStuff(
        [MarshalAs(UnmanagedType::CustomMarshaler,
             MarshalType="MyCompany.NewOldMarshaler")]
        INew^ pINew
    );
};
interface IUserData
{
    void DoSomeStuff(
        [MarshalAs(UnmanagedType.CustomMarshaler,
             MarshalType="MyCompany.NewOldMarshaler")]
        INew pINew
    );
}
Public Interface IUserData
    Sub DoSomeStuff( _
        <MarshalAs(UnmanagedType.CustomMarshaler, _
        MarshalType := "MyCompany.NewOldMarshaler")> pINew As INew)
End Interface

在上一示例中,第一个参数提供给MarshalAsAttribute属性是UnmanagedType.CustomMarshaler枚举值UnmanagedType.CustomMarshalerIn the previous examples, the first parameter provided to the MarshalAsAttribute attribute is the UnmanagedType.CustomMarshaler enumeration value UnmanagedType.CustomMarshaler.

第二个参数是MarshalType字段中,它提供的自定义封送处理程序的程序集限定名称。The second parameter is the MarshalType field, which provides the assembly-qualified name of the custom marshaler. 此名称包含命名空间和类的自定义封送处理程序 (MarshalType="MyCompany.NewOldMarshaler")。This name consists of the namespace and class of the custom marshaler (MarshalType="MyCompany.NewOldMarshaler").

方法

CleanUpManagedData(Object) CleanUpManagedData(Object) CleanUpManagedData(Object) CleanUpManagedData(Object)

不再需要时执行必要的托管数据的清除。Performs necessary cleanup of the managed data when it is no longer needed.

CleanUpNativeData(IntPtr) CleanUpNativeData(IntPtr) CleanUpNativeData(IntPtr) CleanUpNativeData(IntPtr)

不再需要时执行必要的非托管数据的清除。Performs necessary cleanup of the unmanaged data when it is no longer needed.

GetNativeDataSize() GetNativeDataSize() GetNativeDataSize() GetNativeDataSize()

返回要封送的本机数据的大小。Returns the size of the native data to be marshaled.

MarshalManagedToNative(Object) MarshalManagedToNative(Object) MarshalManagedToNative(Object) MarshalManagedToNative(Object)

将托管数据转换为非托管数据。Converts the managed data to unmanaged data.

MarshalNativeToManaged(IntPtr) MarshalNativeToManaged(IntPtr) MarshalNativeToManaged(IntPtr) MarshalNativeToManaged(IntPtr)

将非托管数据转换为托管数据。Converts the unmanaged data to managed data.

适用于