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.