Compartir a través de


Interfaz ICustomMarshaler

 

Publicado: octubre de 2016

Proporciona contenedores personalizados para controlar las llamadas de método.

Espacio de nombres:   System.Runtime.InteropServices
Ensamblado:  mscorlib (en mscorlib.dll)

Sintaxis

[ComVisibleAttribute(true)]
public interface ICustomMarshaler
[ComVisibleAttribute(true)]
public interface class ICustomMarshaler
[<ComVisibleAttribute(true)>]
type ICustomMarshaler = interface end
<ComVisibleAttribute(True)>
Public Interface ICustomMarshaler

Métodos

Nombre Descripción
System_CAPS_pubmethod CleanUpManagedData(Object)

Realiza la limpieza necesaria de los datos administrados cuando ya no es necesario.

System_CAPS_pubmethod CleanUpNativeData(IntPtr)

Realiza la limpieza necesaria de los datos no administrados cuando ya no es necesario.

System_CAPS_pubmethod GetNativeDataSize()

Devuelve el tamaño de los datos nativos que se van a calcular.

System_CAPS_pubmethod MarshalManagedToNative(Object)

Convierte los datos administrados en datos no administrados.

System_CAPS_pubmethod MarshalNativeToManaged(IntPtr)

Convierte los datos no administrados en datos administrados.

Comentarios

Un contador de referencias proporciona un puente entre las funciones de antiguas y nuevas interfaces. Cálculo de referencias personalizado proporciona las siguientes ventajas:

  • Permite que las aplicaciones cliente que se han diseñado para trabajar con una interfaz antigua y funcionar también con servidores que implementan una interfaz nueva.

  • Permite que las aplicaciones cliente diseñadas para funcionar con una interfaz nueva funcionar con servidores que implementan una interfaz antigua.

Si tiene una interfaz que presenta un comportamiento de serialización diferente o que se exponen en el modelo de objetos componentes (COM) de otra forma, puede diseñar un contador de referencias personalizado en lugar de utilizar al serializador de interoperabilidad. Mediante el uso de un contador de referencias personalizado, puede minimizar la distinción entre los nuevos componentes de .NET Framework y los componentes COM existentes.

Por ejemplo, supongamos que está desarrollando una interfaz administrada denominada INew. Cuando esta interfaz se expone a COM mediante un estándar contenedor COM invocable (CCW), tiene los mismos métodos que la interfaz administrada y usa las reglas de cálculo de referencias integradas en el contador de referencias de interoperabilidad. Ahora, supongamos que una interfaz COM conocida denominada IOld ya proporciona la misma funcionalidad que el INew interfaz. Al diseñar un contador de referencias personalizado, puede proporcionar una implementación no administrada de IOld que simplemente delega las llamadas a la implementación administrada de la INew interfaz. Por lo tanto, el contador de referencias personalizado actúa como un puente entre las interfaces administradas y no administradas.

Nota

Contadores de referencias personalizados no se invocan cuando se llama desde código administrado a código no administrado de una interfaz solo de envío.

Definir el tipo de cálculo de referencias

Antes de generar un contador de referencias personalizado, debe definir las interfaces administradas y que se pueden calcular las referencias. Normalmente, estas interfaces realizan la misma función pero se exponen de forma diferente a los objetos administrados y no administrados.

Un compilador administrado produce una interfaz administrada de metadatos y la interfaz resultante es similar a cualquier otra interfaz administrada. En el ejemplo siguiente se muestra una interfaz típica.

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

Definir el tipo no administrado en el lenguaje de definición de interfaz (IDL) y se compila con el compilador de lenguaje de definición de interfaz de Microsoft (MIDL). Definir la interfaz dentro de una instrucción de biblioteca y asignar un identificador de interfaz con el atributo de identificador único universal (UUID), como se muestra en el ejemplo siguiente.

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

El compilador MIDL produce varios archivos de salida. Si la interfaz se define en Old.idl, el archivo de salida Old_i.c define una const variable con el identificador de interfaz (IID) de la interfaz, como se muestra en el ejemplo siguiente.

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

También se genera el archivo Old.h por MIDL. Contiene una definición de la interfaz que puede incluirse en el código fuente de C++ de C++.

Implementar la interfaz ICustomMarshaler

El contador de referencias personalizado debe implementar la ICustomMarshaler interfaz para proporcionar los contenedores adecuados al tiempo de ejecución.

El siguiente código de C# muestra la interfaz base que debe ser implementada por todos los contadores de referencias personalizados.

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
public interface class ICustomMarshaler
{
     Object^ MarshalNativeToManaged( IntPtr^ pNativeData );
     IntPtr^ MarshalManagedToNative( Object^ ManagedObj );
     void CleanUpNativeData( IntPtr^ pNativeData );
     void CleanUpManagedData( Object^ ManagedObj );
     int GetNativeDataSize();
};

El ICustomMarshaler interfaz incluye métodos que proporcionan compatibilidad con la conversión, compatibilidad de limpieza e información sobre los datos que se van a calcular.

Tipo de operación

ICustomMarshaler (método)

Descripción

Conversión (de código nativo a código administrado)

MarshalNativeToManaged

Calcula las referencias de un puntero a datos nativos en un objeto administrado. Este método devuelve un contenedor CCW personalizado en tiempo de ejecución (RCW) que se puede calcular las referencias de la interfaz no administrada que se pasa como argumento. El contador de referencias debe devolver una instancia del contenedor RCW personalizado para ese tipo.

Conversión (de código administrado a nativo)

MarshalManagedToNative

Calcula las referencias de un objeto administrado en un puntero a datos nativos. Este método devuelve un personalizado contenedor COM invocable (CCW) que se puede calcular las referencias de la interfaz administrada que se pasa como argumento. El contador de referencias debe devolver una instancia del contenedor CCW personalizado para ese tipo.

Limpieza (de código nativo)

CleanUpNativeData

Habilita el contador de referencias limpiar los datos nativos (el CCW) devueltos por el MarshalManagedToNative (método).

Limpieza (de código administrado)

CleanUpManagedData

Habilita el contador de referencias limpiar los datos administrados (el contenedor RCW) devueltos por el MarshalNativeToManaged (método).

Información (sobre código nativo)

GetNativeDataSize

Devuelve el tamaño de los datos no administrados que se van a calcular.

Conversión

ICustomMarshaler.MarshalNativeToManaged

Calcula las referencias de un puntero a datos nativos en un objeto administrado. Este método devuelve un contenedor CCW personalizado en tiempo de ejecución (RCW) que se puede calcular las referencias de la interfaz no administrada que se pasa como argumento. El contador de referencias debe devolver una instancia del contenedor RCW personalizado para ese tipo.

ICustomMarshaler.MarshalManagedToNative

Calcula las referencias de un objeto administrado en un puntero a datos nativos. Este método devuelve un personalizado contenedor COM invocable (CCW) que se puede calcular las referencias de la interfaz administrada que se pasa como argumento. El contador de referencias debe devolver una instancia del contenedor CCW personalizado para ese tipo.

Limpieza

ICustomMarshaler.CleanUpNativeData

Habilita el contador de referencias limpiar los datos nativos (el CCW) devueltos por el MarshalManagedToNative (método).

ICustomMarshaler.CleanUpManagedData

Habilita el contador de referencias limpiar los datos administrados (el contenedor RCW) devueltos por el MarshalNativeToManaged (método).

Información de tamaño

ICustomMarshaler.GetNativeDataSize

Devuelve el tamaño de los datos no administrados que se van a calcular.

Implementar el método GetInstance

Además de implementar la ICustomMarshaler interfaz, contadores de referencias personalizados deben implementar un static método llamado GetInstance que acepta un String como un parámetro y tiene un tipo de valor devuelto de ICustomMarshaler. Esto static se invoca mediante la capa de interoperabilidad COM de common language runtime para crear una instancia del contador de referencias personalizado. La cadena que se pasa a GetInstance es una cookie que el método puede utilizar para personalizar el contenedor personalizado devuelto.

static ICustomMarshaler *GetInstance(String *pstrCookie);

Aplicar MarshalAsAttribute

Para utilizar un contador de referencias personalizado, debe aplicar el MarshalAsAttribute al parámetro o campo que se calculan las referencias de atributo.

También se debe pasar la UnmanagedType.CustomMarshaler valor de enumeración para el MarshalAsAttributeconstructor. Además, debe especificar el MarshalType campo con uno de los siguientes parámetros con nombre:

  • MarshalType (obligatorio): el nombre completo del ensamblado del contador de referencias personalizado. El nombre debe incluir el espacio de nombres y la clase de contador de referencias personalizado. Si el contador de referencias personalizado no se define en el ensamblado que se utiliza en, debe especificar el nombre del ensamblado en el que está definido.

    Nota

    Puede usar el MarshalTypeRef campo en lugar de la MarshalType campo.MarshalTypeRef toma un tipo que es fácil de especificar.

  • MarshalCookie (opcional): una cookie que se pasa al contador de referencias personalizado. Puede utilizar la cookie para proporcionar información adicional al contador de referencias. Por ejemplo, si se usa el mismo contador de referencias para proporcionar varios contenedores, la cookie identifica un contenedor específico. La cookie se pasa a la GetInstance método del contador de referencias.

El MarshalAsAttribute atributo identifica el contador de referencias personalizado para que Active el contenedor adecuado. A continuación, servicio de interoperabilidad de common language runtime examina el atributo y crea el tiempo de cálculo de referencias de la primera de las necesidades de argumento (parámetro o campo) que se van a calcular.

El tiempo de ejecución, a continuación, llama a la MarshalNativeToManaged y MarshalManagedToNative métodos en el contador de referencias personalizado para activar el contenedor correcto para controlar la llamada.

Uso de un contador de referencias personalizado

Una vez completado el contador de referencias personalizado, puede usar como contenedor personalizado para un tipo determinado. En el ejemplo siguiente se muestra la definición de la IUserData interfaz administrada:

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

En el ejemplo siguiente, la IUserData usa la interfaz la NewOldMarshaler contador de referencias personalizado para habilitar aplicaciones de cliente no administrado pasar una IOld interfaz para el DoSomeStuff (método). La descripción administrada del DoSomeStuff método toma un INew de interfaz, como se muestra en el ejemplo anterior, mientras que la versión no administrada de DoSomeStuff toma un IOld puntero de interfaz, como se muestra en el ejemplo siguiente.

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

La biblioteca de tipos generada mediante la exportación de la definición administrada de IUserData produce la definición no administrada que se muestra en este ejemplo en lugar de la definición estándar. El MarshalAsAttribute atributo aplicado a la INew argumento en la definición administrada de la DoSomeStuff método indica que el argumento utiliza un contador de referencias personalizado, como se muestra en el ejemplo siguiente.

using System.Runtime.InteropServices;
Imports System.Runtime.InteropServices
using namespace System::Runtime::InteropServices;
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
public interface class IUserData
{
    void DoSomeStuff(
        [MarshalAs(UnmanagedType::CustomMarshaler,
             MarshalType="MyCompany.NewOldMarshaler")]
        INew^ pINew
    );
};

En los ejemplos anteriores, el primer parámetro se proporciona para el MarshalAsAttribute atributo es la UnmanagedType.CustomMarshaler valor de enumeración UnmanagedType.CustomMarshaler.

El segundo parámetro es el MarshalType campo, que proporciona el nombre completo del ensamblado del contador de referencias personalizado. Este nombre consta del espacio de nombres y la clase de contador de referencias personalizado (MarshalType="MyCompany.NewOldMarshaler").

Información de versión

.NET Framework
Disponible desde 1.1

Ver también

Espacio de nombres System.Runtime.InteropServices
Interoperabilidad

Volver al principio