Compartilhar via


Exemplo para resolver conflitos de nome de função

Considere estes fatores:

  • IADs0 não suporta Func0.
  • IADs1 suporta Func1 e Func0.
  • IADs2 suporta Func2 e Func0.

Todas as três interfaces são interfaces duplas.

IADs0 : IDispatch
{
    OtherFunc();
}

IADs1 : IDispatch
{
    Func0() 
    Func1();
}

IADs2 : IDispatch
{
    Func0()
    Func2();
}
Dim myInf1 as IADs1
 
myInf1.Func1  ' IADs1::Func1 is invoked using direct vtable access 
 
myInf1.Func2  ' IADs2::Func2 is invoked using GetIDsOfNames/Invoke

Lembre-se de que, embora os IADs1 não ofereçam suporte a Func2, um cliente ADSI reconhece um IDispatch que oferece suporte a todas as interfaces duplas e de despacho no modelo. Assim, o cliente ADSI pode chamar diretamente Func2 usando myInf1.Func2 sem resolver qual interface suporta Func2.

myInf1.Func2

Os IADs1 e os IADs2 têm uma função chamada Func0, mas os IADs1::Func0 são invocados diretamente usando o acesso vtable, porque ambos se aplicam ao cliente:

  • O cliente tem um ponteiro para o objeto IADs1 de interface dupla, que tem uma função chamada Func0.
  • Visual Basic oferece suporte ao acesso vtable direto, supondo que o tipo de dados está disponível por meio da biblioteca de tipos.

No próximo exemplo de código, o cliente tem um ponteiro de interface dupla para IADs2 em vez de IADs1. Portanto, IADs2::Func0 é invocado usando acesso vtable direto.

Dim myInf2 as IADs2
Set myInf2 = myInf1 ' Query for pointer to IADs2 
myInf2.Func0

Novamente, no próximo exemplo de código, IADs1 e IADs2 têm uma função chamada Func0, mas, aqui, o cliente tem um ponteiro para uma interface dupla, IADs0, que não tem uma função chamada Func0. Portanto, nenhum acesso vtable direto pode ser realizado. Em vez disso, IDispatch::GetIDsOfNames e Invoke são chamados para invocar Func0.

Dim myInfNone as IADs0
Set myInfNone = myInf1    ' The aggregated object that 
   ' supports IADs1 and IADs2.
myInfNone.Func0

Considere estes dois casos:

  • IADs1 e IADs2 são implementados por dois componentes COM, Ext1 e Ext2, respectivamente. Se Ext1 vier antes de Ext2 no registro, IADs1::Func0 será invocado. No entanto, se Ext2 vier primeiro no registro, IADs2::Func0 será invocado.
  • Se IADs1 e ADs2 forem implementados pelo mesmo objeto de extensão, Func0 será sempre invocado pelos métodos IADsExtension::P rivateGetIDsOfNames e PrivateInvoke da extensão.

O desenvolvedor da extensão deve determinar como resolver conflitos de funções, ou propriedades, de diferentes interfaces IDispatch duplas que têm o mesmo nome em uma extensão. A implementação dos métodos IADsExtension::P rivateGetIDsOfNames e PrivateInvoke deve resolver esse conflito. Por exemplo, se você usar IMyInterface1::Func1 e IMyInterface2::Func1, onde IMyInterface1 e IMyInterface2 são interfaces IDispatch duplas suportadas pelo mesmo objeto de extensão. Os métodos PrivateGetIDsOfNames e PrivateInvoke devem determinar qual Func1 sempre deve ser chamado.

O mesmo se aplica a DISPIDs conflitantes em diferentes interfaces duplas ou IDispatch.

Por exemplo, o DISPID de IMyInterface1::Y é 2 no arquivo imyinterface1.odl ou imyinterface1.idl. O DISPID de IMyInterface2::X também é 2 em iMyInterface2.odl. IADsExtension::P rivateGetIDsOfNames deve retornar um DISPID exclusivo, dentro da própria extensão, para cada um, em vez de retornar o mesmo DISPID para ambos.

O ADSI resolve o primeiro problema não oferecendo suporte a várias interfaces com nomes de função ou propriedade conflitantes. Ele resolve o segundo problema adicionando um número de interface exclusivo, que está dentro do mesmo objeto de extensão, para os bits não utilizados do DISPID.