Interface ICustomMarshaler
Dica
The .NET API Reference documentation has a new home. Visit the .NET API Browser on docs.microsoft.com to see the new experience.
Fornece wrappers personalizados para manipular chamadas de método.
Namespace: System.Runtime.InteropServices
Assembly: mscorlib (em mscorlib.dll)
Sintaxe
[ComVisibleAttribute(true)]
public interface ICustomMarshaler
[ComVisibleAttribute(true)]
public interface class ICustomMarshaler
[<ComVisibleAttribute(true)>]
type ICustomMarshaler = interface end
<ComVisibleAttribute(True)>
Public Interface ICustomMarshaler
Métodos
Nome | Descrição | |
---|---|---|
CleanUpManagedData(Object) | Executa a limpeza necessária dos dados gerenciados quando eles não forem mais necessários. |
|
CleanUpNativeData(IntPtr) | Executa a limpeza necessária dos dados não gerenciados quando eles não forem mais necessários. |
|
GetNativeDataSize() | Retorna o tamanho dos dados nativos cujo marshaling deve ser realizado. |
|
MarshalManagedToNative(Object) | Converte os dados gerenciados em dados não gerenciados. |
|
MarshalNativeToManaged(IntPtr) | Converte os dados não gerenciados em dados gerenciados. |
Comentários
Um empacotamento fornece uma ponte entre a funcionalidade antigas e novas interfaces. Empacotamento personalizado oferece os seguintes benefícios:
Ele permite que aplicativos cliente que foram projetados para trabalhar com uma interface antiga também trabalhar com servidores que implementam uma nova interface.
Permite aplicativos cliente criados para funcionar com uma nova interface trabalhar com servidores que implementam uma interface antiga.
Se você tiver uma interface que apresenta o comportamento de marshaling diferente ou que é exposto para o modelo COM (Component Object) de forma diferente, você pode criar um marshaler personalizado em vez de usar o empacotamento de interoperabilidade. Usando um marshaler personalizado, você pode minimizar a distinção entre os novos componentes do .NET Framework e componentes COM existentes.
Por exemplo, suponha que você está desenvolvendo uma interface gerenciada chamada INew. Quando essa interface é exposta a COM por meio de um padrão COM callable wrapper (CCW), ela tem os mesmos métodos de como a interface gerenciada e usa as regras de empacotamento incorporadas interop marshaler. Agora suponha que uma interface COM conhecido chamado IOld já fornecem a mesma funcionalidade que o INew interface. Criando um marshaler personalizado, você pode fornecer uma implementação não gerenciada de IOld que simplesmente delega as chamadas para a implementação gerenciada do INew interface. Portanto, o marshaler personalizado atua como uma ponte entre as interfaces gerenciadas e não gerenciados.
Dica
Marshalers personalizados não serão chamados durante a chamada do código gerenciado para código não gerenciado em uma interface somente de expedição.
Definindo o tipo Marshaling
Antes de criar um marshaler personalizado, você deve definir as interfaces gerenciadas e que irá ser empacotadas. Essas interfaces geralmente realizam a mesma função, mas são expostas diferente para objetos gerenciados e não gerenciados.
Um compilador gerenciado gera uma interface gerenciada dos metadados e a interface resultante parece com qualquer outra interface gerenciada. O exemplo a seguir mostra uma interface comum.
public interface INew
{
void NewMethod();
}
Public Interface INew
Sub NewMethod()
End Interface
public interface class INew
{
void NewMethod();
};
Defina o tipo não gerenciado na Interface Definition Language (IDL) e compilá-lo com o compilador de linguagem de definição de Interface da Microsoft (MIDL). Definir a interface dentro de uma instrução de biblioteca e atribuir uma ID de interface com o atributo de identificador exclusivo universal (UUID), como demonstrado no exemplo a seguir.
[uuid(9B2BAADA-0705-11D3-A0CD-00C04FA35826)]
library OldLib {
[uuid(9B2BAADD-0705-11D3-A0CD-00C04FA35826)]
interface IOld : IUnknown
HRESULT OldMethod();
}
O compilador MIDL produz vários arquivos de saída. Se a interface é definida em Old.idl, o arquivo de saída Old_i.c define um const variável com o identificador de interface (IID) da interface, como demonstrado no exemplo a seguir.
const IID IID_IOld = {0x9B2BAADD,0x0705,0x11D3,{0xA0,0xCD,0x00,0xC0,0x4F,0xA3,0x58,0x26}};
O arquivo de Old.h também é produzido pelo MIDL. Ele contém uma definição de C++ da interface que pode ser incluída em seu código-fonte C++.
Implementando a interface ICustomMarshaler
O marshaler personalizado deve implementar o ICustomMarshaler interface para fornecer os wrappers apropriados para o tempo de execução.
O código c# a seguir exibe a interface base que deve ser implementada por todos os empacotadores 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();
};
O ICustomMarshaler interface inclui métodos que oferecem suporte à conversão, suporte de limpeza e informações sobre os dados a ser empacotado.
Tipo de operação |
Método ICustomMarshaler |
Descrição |
---|---|---|
Conversão (de nativo para código gerenciado) |
Realiza marshaling de um ponteiro para dados nativos em um objeto gerenciado. Esse método retorna um tempo de execução personalizado RCW (callable wrapper) que possa empacotar a interface de não gerenciada é passada como um argumento. O marshaler deve retornar uma instância de RCW personalizado para esse tipo. |
|
Conversão (a partir do código gerenciado para nativo) |
Realiza marshaling de um objeto gerenciado em um ponteiro para dados nativos. Esse método retorna um personalizado COM callable wrapper (CCW) que possa empacotar a interface gerenciada é passada como um argumento. O marshaler deve retornar uma instância da CCW personalizado para esse tipo. |
|
Limpeza (de código nativo) |
Permite que o marshaler limpar os dados nativos (o CCW) que são retornados pelo MarshalManagedToNative método. |
|
Limpeza (de código gerenciado) |
Permite que o marshaler limpar os dados gerenciados (RCW) que são retornados pelo MarshalNativeToManaged método. |
|
Informações (sobre código nativo) |
Retorna o tamanho dos dados não gerenciados para ser empacotado. |
Conversão
ICustomMarshaler.MarshalNativeToManaged
Realiza marshaling de um ponteiro para dados nativos em um objeto gerenciado. Esse método retorna um tempo de execução personalizado RCW (callable wrapper) que possa empacotar a interface de não gerenciada é passada como um argumento. O marshaler deve retornar uma instância de RCW personalizado para esse tipo.
ICustomMarshaler.MarshalManagedToNative
Realiza marshaling de um objeto gerenciado em um ponteiro para dados nativos. Esse método retorna um personalizado COM callable wrapper (CCW) que possa empacotar a interface gerenciada é passada como um argumento. O marshaler deve retornar uma instância da CCW personalizado para esse tipo.
Limpeza
ICustomMarshaler.CleanUpNativeData
Permite que o marshaler limpar os dados nativos (o CCW) que são retornados pelo MarshalManagedToNative método.
ICustomMarshaler.CleanUpManagedData
Permite que o marshaler limpar os dados gerenciados (RCW) que são retornados pelo MarshalNativeToManaged método.
Informações de tamanho
ICustomMarshaler.GetNativeDataSize
Retorna o tamanho dos dados não gerenciados para ser empacotado.
Implementando o método GetInstance
Além de implementar o ICustomMarshaler interface empacotadores personalizados devem implementar um static método chamado GetInstance que aceita um String como um parâmetro e tem um tipo de retorno ICustomMarshaler. Isso static método é chamado pela camada de interoperabilidade COM o common language runtime para criar uma instância do marshaler personalizado. A cadeia de caracteres que é passada para GetInstance é um cookie que o método pode usar para personalizar o marshaler personalizado retornado.
static ICustomMarshaler *GetInstance(String *pstrCookie);
Aplicando MarshalAsAttribute
Para usar um marshaler personalizado, você deve aplicar o MarshalAsAttribute de atributo para o parâmetro ou campo que está sendo empacotado.
Você também deve transmitir o UnmanagedType.CustomMarshaler valor de enumeração para o MarshalAsAttributeconstrutor. Além disso, você deve especificar o MarshalType campo com um dos seguintes parâmetros nomeados:
MarshalType(obrigatório): O nome qualificado de assembly do marshaler personalizado. O nome deve incluir o namespace e classe de marshaler personalizado. Se o marshaler personalizado não está definido no assembly em que é usado, você deve especificar o nome do assembly no qual ela está definida.
Dica
Você pode usar o MarshalTypeRef campo em vez do MarshalType campo.MarshalTypeRefusa um tipo que é mais fácil de especificar.
MarshalCookie(opcional): um cookie que é passado para o marshaler personalizado. Você pode usar o cookie para fornecer informações adicionais para o empacotador. Por exemplo, se o mesmo marshaler é usado para fornecer um número de wrappers, o cookie identifica um wrapper específico. O cookie é passado para o GetInstance método de empacotamento.
O MarshalAsAttribute atributo identifica o marshaler personalizado para que ele pode ativar o wrapper apropriado. Serviço de interoperabilidade do common language runtime, em seguida, examina o atributo e cria o tempo de marshaler personalizado primeiro o argumento (parâmetro ou campo) precisa ser empacotado.
O tempo de execução, em seguida, chama o MarshalNativeToManaged e MarshalManagedToNative métodos em que o marshaler personalizado para ativar o wrapper correto para manipular a chamada.
Usando um Marshaler personalizado
Quando o marshaler personalizado for concluído, você pode usá-lo como um wrapper personalizado para um determinado tipo. O exemplo a seguir mostra a definição do IUserData interface gerenciada:
interface IUserData
{
void DoSomeStuff(INew pINew);
}
Public Interface IUserData
Sub DoSomeStuff(pINew As INew)
End Interface
public interface class IUserData
{
void DoSomeStuff(INew^ pINew);
};
No exemplo a seguir, o IUserData interface usos de NewOldMarshaler marshaler personalizado para permitir que aplicativos cliente não gerenciados passar um IOld interface para o DoSomeStuff método. A descrição do gerenciado do DoSomeStuff leva um INew de interface, conforme mostrado no exemplo anterior, enquanto a versão não gerenciada de DoSomeStuff leva um IOld ponteiro de interface, conforme mostrado no exemplo a seguir.
[uuid(9B2BAADA-0705-11D3-A0CD-00C04FA35826)]
library UserLib {
[uuid(9B2BABCD-0705-11D3-A0CD-00C04FA35826)]
interface IUserData : IUnknown
HRESULT DoSomeStuff(IUnknown* pIOld);
}
A biblioteca de tipos que é gerada por meio da exportação a definição gerenciada da IUserData gera a definição não gerenciada mostrada neste exemplo, em vez da definição padrão. O MarshalAsAttribute atributo aplicado para o INew argumento a definição gerenciada do DoSomeStuff método indica que o argumento usa um marshaler personalizado, como mostra o exemplo a seguir.
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
);
};
Nos exemplos anteriores, o primeiro parâmetro fornecido para o MarshalAsAttribute atributo é o UnmanagedType.CustomMarshaler valor de enumeração UnmanagedType.CustomMarshaler.
O segundo parâmetro é o MarshalType campo, que fornece o nome qualificado de assembly do marshaler personalizado. Esse nome consiste o namespace e classe de personalizado (MarshalType="MyCompany.NewOldMarshaler").
Informações de Versão
.NET Framework
Disponível desde 1.1
Confira Também
Namespace System.Runtime.InteropServices
Interoperabilidade
Retornar ao início