Apresentando a Interface de classe
A interface de classe, o que não é definida explicitamente em código gerenciado, é uma interface que expõe todos os métodos públicos, propriedades, campos e eventos que são explicitamente expostos na.NET object. Esta interface pode ser uma interface dual ou somente de distribuição. A interface de classe recebe o nome da.NET própria classe, precedido por um sublinhado. Por exemplo, para a classe mamífero, a interface de classe é _Mammal.
Para classes derivadas, a interface de classe também expõe todos os campos da classe base, propriedades e métodos públicos. A classe derivada também expõe uma interface de classe para cada classe de base. Por exemplo, se a classe mamífero estende a classe MammalSuperclass, que estende System. Object, o.NET object expõe para COM clientes três interfaces de classe denominado _Mammal, _MammalSuperclass e _Object.
Por exemplo, considere o seguinte.NET classe:
' Applies the ClassInterfaceAttribute to set the interface to dual.
<ClassInterface(ClassInterfaceType.AutoDual)> _
' Implicitly extends System.Object.
Public Class Mammal
Sub Eat()
Sub Breathe()
Sub Sleep()
End Class
// Applies the ClassInterfaceAttribute to set the interface to dual.
[ClassInterface(ClassInterfaceType.AutoDual)]
// Implicitly extends System.Object.
public class Mammal
{
void Eat();
void Breathe():
void Sleep();
}
O cliente COM pode obter um ponteiro para uma interface de classe chamada _Mammal, que é descrito na biblioteca de tipos que o Type Library Exporter (Tlbexp. exe) ferramenta gera. Se o Mammal classe implementada uma ou mais interfaces, interfaces apareceria em coclass.
[odl, uuid(…), hidden, dual, nonextensible, oleautomation]
interface _Mammal : IDispatch
{
[id(0x00000000), propget] HRESULT ToString([out, retval] BSTR*
pRetVal);
[id(0x60020001)] HRESULT Equals([in] VARIANT obj, [out, retval]
VARIANT_BOOL* pRetVal);
[id(0x60020002)] HRESULT GetHashCode([out, retval] short* pRetVal);
[id(0x60020003)] HRESULT GetType([out, retval] _Type** pRetVal);
[id(0x6002000d)] HRESULT Eat();
[id(0x6002000e)] HRESULT Breathe();
[id(0x6002000f)] HRESULT Sleep();
}
[uuid(…)]
coclass Mammal
{
[default] interface _Mammal;
}
Gerando a interface de classe é opcional. Por padrão, a interoperabilidade COM gera uma interface somente de distribuição para cada classe que você exportar para uma biblioteca de tipos. Você pode evitar ou modificar a criação automática desta interface aplicando o ClassInterfaceAttribute para sua turma. Embora a interface de classe pode facilitar a tarefa de expor classes gerenciadas para COM, seus usos são limitados.
Cuidado |
---|
Usando a interface de classe, em vez de explicitamente definir seu próprio, podem complicar as versões futuras da sua classe gerenciada.Leia as diretrizes a seguir antes de usar a interface de classe. |
Defina uma interface explícita para clientes COM uso em vez de gerar a interface de classe.
Porque a interoperabilidade COM gera automaticamente uma interface de classe, post-version alterações à sua classe podem alterar o layout da interface de classe exposto pelo common language runtime. Como os clientes COM são normalmente despreparados lidar com alterações no layout de uma interface, eles quebraram se você alterar o layout do membro da classe.
Essa diretriz reforça a noção de que as interfaces expostas para clientes COM devem permanecer inalterável. Para reduzir o risco de quebrar a clientes COM reordenando inadvertidamente o layout da interface, isole todas as alterações à classe do layout de uma interface definindo explicitamente as interfaces.
Use o ClassInterfaceAttribute para desengatar a geração automática de interface de classe e implementar uma interface explícita para a classe, conforme mostrado no fragmento de código seguinte:
<ClassInterface(ClassInterfaceType.None)>Public Class LoanApp
Implements IExplicit
Sub M() Implements IExplicit.M
…
End Class
[ClassInterface(ClassInterfaceType.None)]
public class LoanApp : IExplicit {
void M();
}
O ClassInterfaceType. None valor impede que a interface de classe que estão sendo gerados quando os metadados da classe é exportado para uma biblioteca de tipos. No exemplo anterior, os clientes COM podem acessar o LoanApp classe somente por meio de IExplicit interface.
Evite o armazenamento em cache os identificadores de despacho (DispIds).
Usando a interface de classe é uma opção aceitável para o script, os clientes Microsoft Visual Basic 6.0 ou qualquer cliente de ligação tardia não armazena em cache os DispIds de membros de interface. DispIds identificar membros de interface para permitir a ligação tardia.
Para a interface de classe, a geração de DispIds baseia-se na posição do membro na interface. Se você alterar a ordem do membro e exporta a classe para uma biblioteca de tipos, você alterará os DispIds gerado na interface de classe.
Para evitar a interrupção de clientes de COM ligação tardia ao usar a interface de classe, aplicar o ClassInterfaceAttribute com o ClassInterfaceType.AutoDispatch valor. Esse valor implementa uma interface de classe somente de distribuição, mas omite a descrição da interface de biblioteca de tipos. Sem uma descrição de interface, os clientes conseguem cache DispIds em tempo de compilação. Embora esse seja o tipo de interface padrão para a interface de classe, você pode aplicar o valor do atributo explicitamente.
<ClassInterface(ClassInterfaceType.AutoDispatch)> Public Class LoanApp
Implements IAnother
Sub M() Implements IAnother.M
…
End Class
[ClassInterface(ClassInterfaceType.AutoDispatch]
public class LoanApp : IAnother {
void M();
}
Para obter o DispId de um membro de interface em tempo de execução, os clientes COM podem chamar IDispatch.GetIdsOfNames. Para chamar um método na interface, passe o DispId retornado como um argumento para IDispatch.
Restringir o uso da opção de interface dupla para a interface de classe.
Interfaces duplas permitem a ligação antecipada e atrasada para membros de interface por clientes COM. Em tempo de design e durante o teste, talvez seja útil para definir a interface de classe para dois. Para uma classe gerenciada (e suas classes base) que nunca será modificada, essa opção também é aceitável. Em outros casos, evite a definição de interface de classe dual.
Uma interface dupla gerada automaticamente pode ser adequada em casos raros; No entanto, com mais freqüência cria complexidade relacionados à versão. Por exemplo, os clientes de COM usando a interface de classe de uma classe derivada podem quebrar facilmente com as alterações para a classe base. Quando um terceiro fornece a classe base, o layout da interface de classe está fora do seu controle. Além disso, ao contrário de uma interface somente de distribuição, uma interface dupla (ClassInterface.AutoDual) fornece uma descrição da interface de classe na biblioteca de tipos exportados. Como uma descrição incentiva os clientes de ligação tardia DispIds do cache em tempo de execução.