Compartilhar via


Criando componentes de COM para interoperação

Se você planeja escrever aplicativos baseados em COM no futuro, você pode criar seu código para interoperar com código gerenciado com eficiência.Com planejamento avançado, você também pode simplificar a migração de código não gerenciado para código gerenciado.

As recomendações a seguir resumem as práticas recomendadas para escrever tipos COM que interagem com código gerenciado.

Fornece bibliotecas de tipos

Na maioria das situações, o common linguagem tempo de execução requer metadados para todos os tipos, incluindo tipos COM.The Tipo biblioteca Importer (Tlbimp.exe), incluído no Windows Software Development Kit (SDK), pode converter bibliotecas de tipo COM metadados do .NET estrutura. Depois que a biblioteca de tipos é convertida em metadados, clientes gerenciado podem chamar o tipo COM sem problemas.Para facilitar o uso, sempre fornecer informações de tipo em uma biblioteca de tipos.

Você pode empacotar uma biblioteca de tipos sistema autônomo um arquivo separado ou incorporá-lo sistema autônomo um recurso dentro de um arquivo .dll, .exe ou .ocx.Além disso, você pode gerar metadados diretamente, que permite que você entre os metadados com o emparelhar de chaves do publicador.Assinado com uma chave de metadados tem uma fonte definitiva e podem ajudar a evitar a vinculação quando o chamador tem a chave errada, assim, aumentar a segurança.

Registrar bibliotecas de tipos

Para realizar realizar marshaling chamadas corretamente, o tempo de execução pode ser necessário localizar a biblioteca de tipos que descreve um tipo específico.Uma biblioteca de tipos deve ser registrada antes do tempo de execução pode vê-lo, exceto no caso de associação tardia.

Você pode registrar uma biblioteca de tipos, chamar a API do Microsoft Win32 LoadTypeLibEx função com o regkind sinalizar definido como REGKIND_REGISTER.Regsvr32.exe registra automaticamente uma biblioteca de tipos incorporada em um arquivo .dll.

Use segurança arrays em vez de matrizes de comprimento variável

COM os arrays seguros são autodescritivos.Examinando a matriz segura, o empacotador de time de execução pode determinar a posição, dimensionar, limites e geralmente o tipo do Sumário da matriz em time de execução.Comprimento variável (ou estilo C) arrays não têm a mesma qualidade autodescritivo.Por exemplo, a seguinte assinatura de método não-gerenciado não fornece nenhuma informação sobre o parâmetro de matriz diferente do tipo de elemento.

HRESULT DoSomething(int cb, [in] byte buf[]);

Na verdade, a matriz é idêntico a qualquer Outros parâmetro passado por referência.sistema autônomo resultado, o Tlbimp.exe não converte o parâmetro de matriz do DoSomething método. Em vez disso, a matriz é exibido sistema autônomo uma referência a um Byte tipo, sistema autônomo o código a seguir mostra.

Public Sub DoSomething(cb As Integer, ByRef buf As Byte)
public void DoSomething(int cb, ref Byte buf);

Para melhorar a interoperação, você pode digitar o argumento sistema autônomo um SAFEARRAY na assinatura do método não gerenciado.Por exemplo:

HRESULT DoSomething(SAFEARRAY(byte)buf);

Tlbimp.exe converte o SAFEARRAY no seguinte do tipo matriz gerenciada:

Public Sub DoSomething(buf As Byte())
public void DoSomething(Byte[] buf);

Usar tipos de dados em conformidade com a automação

O tempo de execução do marshaling automaticamente serviço suporta todos os tipos de dados compatível com automação.Tipos que não são compatíveis com talvez ou talvez não tenham suporte.

Fornecer versão e a localidade em bibliotecas de tipos

Quando você importar uma biblioteca de tipos, as informações de versão e a localidade de biblioteca do tipo também são propagadas para o assembly.Clientes gerenciado, em seguida, podem BIND a uma versão específica ou a localidade do assembly ou para a versão mais recente do assembly.Fornecendo informações de versão na biblioteca de tipos permite que os clientes escolher precisamente qual versão do assembly usar.

Use tipos Blittable

Tipos de dados são blittable ou não blittable.Tipos blittable têm uma representação comum entre o limite de interoperabilidade.Número inteiro e tipos de ponto flutuante são blittable.Matrizes e estruturas de tipos blittable são também blittable.Cadeias de caracteres, datas e objetos são exemplos de tipos blittable não convertidos durante o processo de marshaling.

Tipos blittable e blittable não são suportados pelo marshaling de interoperabilidade serviço; no entanto, tipos requerem conversão durante o empacotamento não executam bem sistema autônomo tipos blittable.Ao usar tipos blittable não, esteja ciente de que existe é adicionada sobrecarga associada marshaling-los.

Seqüências de caracteres são particularmente problemáticas.Seqüências de caracteres gerenciadas são armazenadas sistema autônomo caracteres Unicode e, conseqüentemente, podem ser empacotadas com maior eficiência para código não gerenciado que espera sistema autônomo argumentos de caractere Unicode.É melhor evitar seqüências compostas de caracteres ANSI quando possível.

Implementar IProvideClassInfo

Quando se faz o marshaling de interfaces de não gerenciados para código gerenciado, o tempo de execução cria um wrapper de um tipo específico.A assinatura do método normalmente indica o tipo da interface, mas o tipo de objeto que implementa a interface pode ser desconhecido.Se o tipo de objeto for desconhecido, o tempo de execução empacota a interface com um invólucro genérica de objeto COM, que é menos funcional que invólucros específicas do tipo.

Por exemplo, considere a seguinte assinatura de método COM:

interface INeedSomethng {
   HRESULT DoSomething(IBiz *pibiz);
}

Quando importado, o método é convertido da seguinte maneira:

Interface INeedSomething
   Sub DoSomething(pibiz As IBiz)
End Interface
interface INeedSomething {
   void DoSomething(IBiz pibiz);
}

Se você passar um objeto gerenciado que implementa o INeedSomething interface para o IBiz interface, o interop marshaler tenta dispor a interface com um wrapper do objeto de um tipo específico sobre o lançamento inicial do IBiz código gerenciado para. Para identificar o tipo correto de wrapper, o empacotador deve saber o tipo de objeto que implementa a interface.É uma maneira de empacotamento tenta determinar o tipo de objeto é a consulta para o IProvideClassInfo interface.Se o objeto implementa IProvideClassInfo, o empacotador determina o tipo do objeto e encapsula a interface em um wrapper de tipos.

Usar chamadas modulares

marshaling de dados entre código gerenciado e tem um custo.Você pode atenuar o custo, tornando menos transições entre o limite.Interfaces que minimizam o número de transições de geralmente desempenho melhor do que interfaces que ultrapassam o limite com freqüência, execução de tarefas pequenas com cada interseção.

Use falha HRESULTs conservadoramente

Quando um cliente gerenciado chama um objeto COM, o tempo de execução mapeia falha do objeto COM HRESULTs para exceções, que lança o empacotador no retorno de telefonar.O gerenciado modelo exceção foi otimizado para casos que não são excepcionais; não há quase nenhuma sobrecarga associada à captura exceções quando nenhuma exceção ocorre.Por outro lado, quando ocorre uma exceção, captura a exceção pode ser caro.

Use exceções com moderação e evite retornando HRESULTs falha para fins Informativo.Reserve falha HRESULTs para situações excepcionais.Perceba que o uso excessivo de falha HRESULTS pode afetar o desempenho.

disponível Externo recursos explicitamente

Alguns objetos usam recursos externos durante sua tempo de vida; por exemplo, uma conexão de banco de dados, pode atualizar um conjunto de registros.Normalmente, um objeto mantiver um recurso externo para a duração da sua tempo de vida, enquanto uma versão explícita pode retornar imediatamente o recurso.Por exemplo, você pode usar o Fechar método em um objeto de arquivo em vez de fechar o arquivo no destruidor de classe ou com IUnknown.versão.Fornecendo um equivalente à Fechar método no seu código, você pode liberar o recurso de arquivo externo, mesmo que o objeto para o arquivo continua a existir.

Evitar redefinindo tipos não gerenciados

A maneira correta para implementar uma interface COM existente no código gerenciado é para começar, importar a definição de interface com o Tlbimp.exe ou uma API equivalente.Os metadados resultante fornecem uma definição compatível da interface COM (mesmo IID, mesmo DispIds e assim por diante).

Evite redefinindo interfaces COM manualmente no código gerenciado.Esta tarefa consome time e raramente produz uma interface gerenciada compatível com a interface COM existente.Em vez disso, use o Tlbimp.exe para manter a compatibilidade de definição.

Evite usar HRESULTs sucesso

Capturar exceções é a maneira mais natural para aplicativos gerenciado lidar com situações de erro.Para tornar o uso de tipos COM transparente, o tempo de execução lança uma exceção automaticamente sempre que um método COM retorna uma falha HRESULT.

Se seu objeto COM retorna um HRESULT de sucesso, o tempo de execução retorna qualquer valor é no retval parâmetro.Por padrão, o HRESULT é descartado, tornando muito difícil para o cliente gerenciado examinar o valor de um sucesso HRESULT.Embora você pode preservar um HRESULT com o PreserveSigAttribute atributo, o processo requer esforço. Você deve adicionar manualmente o atributo a um assembly gerado com Tlbimp.exe ou uma API equivalente.

É melhor evitar sucesso HRESULTs sempre que possível.Em vez disso, você pode retornar informações sobre o status de uma telefonar através de um parâmetro de saída.

Evite usar funções do módulo

Bibliotecas de tipos podem conter funções definidas em um módulo.Normalmente, você deve usar essas funções para fornecer informações de tipo para pontos de entrada DLL.Tlbimp.exe não importa essas funções.

Evite usar membros de sistema.objeto em interfaces padrão

Clientes gerenciado e COM coclasses interagem com a Ajuda de wrappers fornecidos pelo tempo de execução.Quando você importa um tipo COM, o processo de conversão adiciona todos os métodos da interface padrão do coclass à classe de invólucro, que deriva do System.Object classe. Tenha cuidado para nomes de membros da interface padrão para que não ocorram conflitos de nomes com os membros de sistema.objeto.Se ocorrer um conflito, o método importado substitui o método da classe base.

Essa ação pode ser favorável se o método de interface padrão e o método de sistema.objeto fornecem a mesma funcionalidade.Ele pode ser problemático, no entanto, se forem usados métodos da interface padrão de modo não intencional.Para evitar conflitos de nomes, evite usar os seguintes nomes de interfaces padrão: Objeto, Equals, Finalize GetHashCode, GetType, MemberwiseClone e ToString.

Consulte também

Referência

Tipo Biblioteca Importer (Tlbimp.exe)

Outros recursos

Considerações sobre design de interoperação