Compartilhar via


Realizando marshaling de interoperabilidade

O marshaling de interoperabilidade controla como os dados são passados em argumentos de método e valores retornados entre memória gerenciada e não gerenciada e durante chamadas. O marshaling de interoperabilidade é uma atividade de tempo de execução executada pelo serviço de marshaling do Common Language Runtime.

A maioria dos tipos de dados tem representações comuns na memória gerenciada e não gerenciada. O marshaler de interoperabilidade manipula esses tipos para você. Outros tipos podem ser ambíguos ou não representados na memória gerenciada.

Um tipo ambíguo pode ter múltiplas representações não gerenciadas que correspondem a um único tipo gerenciado, ou informações de tipo ausentes, como o tamanho de uma matriz. Para tipos ambíguos, o marshaller fornece uma representação padrão e representações alternativas em que existem várias representações. Você pode fornecer instruções explícitas para o marshaler sobre como ele deve realizar marshaling de um tipo ambíguo.

Invocação de plataforma e modelos de interoperabilidade COM

O common language runtime fornece dois mecanismos para interoperação com código não gerenciado:

  • Invocação de plataforma, que permite que o código gerenciado chame funções exportadas de uma biblioteca não gerenciada.
  • Interoperabilidade COM, que permite que o código gerenciado interaja com objetos COM (Component Object Model) por meio de interfaces.

Tanto a invocação de plataforma quanto a interoperabilidade COM usam marshaling de interoperabilidade para mover com precisão os argumentos de método entre o chamador e o receptor e vice-versa, se necessário. Conforme mostra a ilustração a seguir, uma chamada de método de invocação de plataforma flui do código gerenciado para código não gerenciado e nunca na direção contrária, exceto quando funções de retorno de chamada estão envolvidas. Embora as chamadas de invocação de plataforma possam fluir apenas de código gerenciado para não gerenciado, os dados podem fluir em ambas as direções como parâmetros de entrada ou saída. As chamadas de método de interoperabilidade COM podem fluir em ambas as direções.

Invocação de plataforma

No nível mais baixo, ambos os mecanismos usam o mesmo serviço de marshaling de interoperabilidade; no entanto, alguns tipos de dados têm suporte apenas pela interoperabilidade COM ou pela invocação de plataforma. Para obter detalhes, confira Comportamento de marshaling padrão.

Marshaling e apartments COM

O marshaler de interoperabilidade realiza marshaling de dados entre o heap do Common Language Runtime e o heap não gerenciado. O marshaling ocorre sempre que o chamador e o receptor não podem operar na mesma instância dos dados. O marshaler de interoperabilidade torna possível que o chamador e o receptor pareçam estar funcionando nos mesmos dados, mesmo que eles tenham sua própria cópia dos dados.

O COM também tem um marshaler que realiza marshaling de dados entre apartments COM ou processos COM diferentes. Ao chamar entre código gerenciado e código não gerenciado dentro do mesmo apartment COM, o marshaler de interoperabilidade é o único marshaler envolvido. Ao chamar entre código gerenciado e o código não gerenciado em um apartment COM diferente ou um processo diferente, tanto o marshaler de interoperabilidade quanto o marshaler COM estão envolvidos.

Clientes COM e servidores gerenciados

Um servidor gerenciado exportado com uma biblioteca de tipos registrada pelo Regasm.exe (Ferramenta de Registro de Assembly) tem uma ThreadingModel entrada do Registro definida como Both. Esse valor indica que o servidor pode ser ativado em um STA (apartamento com thread único) ou em um MTA (apartamento multithreaded). O objeto de servidor é criado no mesmo apartamento que o chamador, conforme mostrado na tabela a seguir:

Cliente COM Servidor .NET Requisitos de marshaling
STA Both se torna STA. Marshaling no mesmo apartment.
MTA Both se torna MTA. Marshaling no mesmo apartment.

Já que o cliente e o servidor estão no mesmo apartment, o serviço de marshaling de interoperabilidade manipula automaticamente todo o marshaling de dados. A ilustração a seguir mostra o serviço de marshaling de interoperabilidade funcionando entre heaps gerenciados e não gerenciados dentro do mesmo apartment de estilo COM.

Marshaling de interoperabilidade entre heaps gerenciados e não gerenciados

Se você planeja exportar um servidor gerenciado, lembre-se de que o cliente COM determina o apartamento do servidor. Um servidor gerenciado chamado por um cliente COM inicializado em um MTA deve garantir a segurança do thread.

Clientes gerenciados e servidores COM

A configuração padrão para apartamentos de cliente gerenciado é MTA; no entanto, o tipo de aplicativo do cliente .NET pode alterar a configuração padrão. Por exemplo, a configuração de apartment de um cliente do Visual Basic é STA. Você pode usar uma das propriedades System.STAThreadAttribute, System.MTAThreadAttribute, Thread.ApartmentState ou Page.AspCompatMode para examinar e alterar a configuração de apartment de um cliente gerenciado.

O autor do componente define a afinidade de thread de um servidor COM. A tabela a seguir mostra as combinações de configurações de apartment de clientes .NET e servidores COM. Ele também mostra os requisitos de marshaling resultantes para as combinações.

Cliente .NET Servidor COM Requisitos de marshaling
MTA (padrão) MTA

STA
Marshalling de interoperação.

Marshaling COM e de interoperabilidade.
STA MTA

STA
Marshaling COM e de interoperabilidade.

Marshalling de interoperação.

Quando um cliente gerenciado e servidor não gerenciado estão no mesmo apartment, o serviço de marshaling de interoperabilidade manipula todo o marshaling de dados. No entanto, quando o cliente e servidor são inicializados em apartments diferentes, o marshaling de COM também é necessário. A ilustração a seguir mostra os elementos de uma chamada entre apartments:

Chamada entre apartments entre um cliente .NET e um objeto COM

Para realizar marshaling entre apartments, você pode fazer o seguinte:

  • Aceite a sobrecarga do marshaling entre apartments, que é perceptível somente quando há muitas chamadas no limite. Você deve registrar a biblioteca de tipos do componente COM para que as chamadas possam cruzar com sucesso o limite do apartamento.

  • Altere o thread principal definindo o thread do cliente como STA ou MTA. Por exemplo, se o cliente C# chama muitos componentes COM STA, você pode evitar o marshaling entre apartments definindo o thread principal como STA.

    Observação

    Depois que o thread de um cliente C# for definido como STA, chamadas para componentes COM MTA exigirão marshaling entre apartments.

Para obter instruções sobre como selecionar explicitamente um modelo de apartamento, consulte Managed and Unmanaged Threading.

Marshaling de chamadas remotas

Assim como ocorre com marshaling entre apartments, o marshaling COM está envolvido em cada chamada entre código gerenciado e código não gerenciado e sempre que os objetos residem em processos separados. Por exemplo:

  • Um cliente COM que invoca um servidor gerenciado em um host remoto usa COM distribuído (DCOM).
  • Um cliente gerenciado que invoca um servidor COM em um host remoto usa DCOM.

A ilustração a seguir mostra como o marshaling de interoperabilidade e o marshaling COM fornecem canais de comunicação entre os limites de processo e de host:

Marshaling entre processos

Preservando identidade

O common language runtime preserva a identidade de referências gerenciadas e não gerenciadas. A ilustração a seguir mostra o fluxo de referências não gerenciadas diretas (linha superior) e referências gerenciadas diretas (linha inferior) entre limites de processo e host.

Wrapper que pode ser chamado por COM e wrapper que pode ser chamado em runtime

Nesta ilustração:

  • Um cliente não gerenciado obtém uma referência a um objeto COM de um objeto gerenciado que obtém essa referência de um host remoto. O mecanismo de comunicação remota é DCOM.

  • Um cliente gerenciado obtém uma referência a um objeto gerenciado de um objeto COM que obtém essa referência de um host remoto. O mecanismo de comunicação remota é DCOM.

    Observação

    A biblioteca de tipos exportada do servidor gerenciado deve ser registrada.

O número de limites de processo entre o chamador e o receptor é irrelevante; a mesma referência direta ocorre tanto para chamadas dentro do processo quanto fora dele.

Comunicação remota gerenciada

O runtime também fornece comunicação remota gerenciada, que você pode usar para estabelecer um canal de comunicação entre objetos gerenciados entre os limites do processo e do host. A comunicação remota gerenciada pode acomodar um firewall entre os componentes de comunicação, como mostra a ilustração a seguir:

SOAP ou TcpChannel Chamadas remotas entre firewalls usando SOAP ou a classe TcpChannel

Algumas chamadas não gerenciadas podem ser canalizadas por meio de SOAP, como as chamadas entre componentes atendidos e COM.

Título Descrição
Comportamento de marshaling padrão Descreve as regras que o serviço de marshaling de interoperabilidade usa para realizar marshaling de dados.
Realizar marshaling de dados com invocação de plataforma Descreve como declarar parâmetros de método e passar argumentos para funções exportadas por bibliotecas não gerenciadas.
Como realizar marshaling em dados com a interoperabilidade COM Descreve como personalizar os wrappers COM para alterar o comportamento de marshaling.
Como migrar Managed-Code DCOM para o WCF Descreve como migrar do DCOM para o WCF.
Como: Mapear HRESULTs e exceções Descreve como mapear exceções personalizadas para HRESULTs e fornece o mapeamento completo de cada HRESULT para sua classe de exceção comparável no .NET Framework.
Interoperação usando tipos genéricos Descreve quais ações têm suporte ao usar tipos genéricos para interoperabilidade COM.
Interoperação com código não gerenciado Descreve os serviços de interoperabilidade fornecidos pelo common language runtime.
Interoperabilidade Avançada COM Fornece links para obter mais informações sobre como incorporar componentes COM ao seu aplicativo .NET Framework.
Considerações de design para interoperação Fornece dicas para escrever componentes COM integrados.

Referência

System.Runtime.InteropServices