Exemple de résolution des conflits de noms de fonction
Tenez compte des éléments suivants :
- IADs0 ne prend pas en charge Func0.
- IADs1 prend en charge Func1 et Func0.
- IADs2 prend en charge Func2 et Func0.
Les trois interfaces sont des interfaces doubles.
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
N’oubliez pas que même si IADs1 ne prend pas en charge Func2, un client ADSI reconnaît une IDispatch qui prend en charge toutes les interfaces double et de répartition dans le modèle. Ainsi, le client ADSI peut appeler directement Func2 à l’aide de myInf1.Func2 sans déterminer quelle interface prend en charge Func2.
myInf1.Func2
IADs1 et IADs2 ont une fonction appelée Func0, mais IADs1::Func0 est appelé directement à l’aide de l’accès vtable, car les deux éléments suivants s’appliquent au client :
- Le client a un pointeur vers l’objet IADs1 double interface, qui a une fonction appelée Func0.
- Visual Basic prend en charge l’accès direct aux tables virtuelles, en supposant que ce type de données est disponible via la bibliothèque de types.
Dans l’exemple de code suivant, le client a un pointeur d’interface double vers IADs2 au lieu de IADs1. Par conséquent, IADs2::Func0 est appelé à l’aide d’un accès direct à la table virtuelle.
Dim myInf2 as IADs2
Set myInf2 = myInf1 ' Query for pointer to IADs2
myInf2.Func0
Là encore, dans l’exemple de code suivant, IADs1 et IADs2 ont une fonction appelée Func0, mais, ici, le client a un pointeur vers une interface double, IADs0, qui n’a pas de fonction appelée Func0. Par conséquent, aucun accès direct à la table virtuelle ne peut être effectué. Au lieu de cela, IDispatch::GetIDsOfNames et Invoke sont appelés pour appeler Func0.
Dim myInfNone as IADs0
Set myInfNone = myInf1 ' The aggregated object that
' supports IADs1 and IADs2.
myInfNone.Func0
Considérez ces deux cas :
- IADs1 et IADs2 sont implémentés par deux composants COM, Ext1 et Ext2, respectivement. Si Ext1 est antérieur à Ext2 dans le Registre, IADs1::Func0 est appelé. Toutefois, si Ext2 figure en premier dans le Registre, IADs2::Func0 est appelé.
- Si IADs1 et ADs2 sont implémentés par le même objet d’extension, Func0 est toujours appelé par les méthodes IADsExtension::P rivateGetIDsOfNames et PrivateInvoke de l’extension .
Le développeur d’extension doit déterminer comment résoudre les conflits de fonctions, ou de propriétés, de différentes interfaces IDispatch doubles qui ont le même nom dans une extension. L’implémentation des méthodes IADsExtension::P rivateGetIDsOfNames et PrivateInvoke doit résoudre ce conflit. Par exemple, si vous utilisez IMyInterface1::Func1 et IMyInterface2::Func1, où IMyInterface1 et IMyInterface2 sont des interfaces IDispatch doubles prises en charge par le même objet d’extension. Les méthodes PrivateGetIDsOfNames et PrivateInvoke doivent déterminer le Func1 qui doit toujours être appelé.
Il en va de même pour les DISPID en conflit dans différentes interfaces doubles ou IDispatch .
Par exemple, la valeur DISPID de IMyInterface1::Y est 2 dans le fichier imyinterface1.odl, ou imyinterface1.idl. Le DISPID de IMyInterface2::X est également 2 dans iMyInterface2.odl. IADsExtension::P rivateGetIDsOfNames doit retourner un DISPID unique, dans l’extension elle-même, pour chacun, au lieu de retourner le même DISPID pour les deux.
ADSI résout le premier problème en ne prenant pas en charge plusieurs interfaces avec des noms de fonctions ou de propriétés en conflit. Il résout le deuxième problème en ajoutant un numéro d’interface unique, qui se trouve dans le même objet d’extension, aux bits inutilisés du DISPID.