Beispiel für das Auflösen von Funktionsnamenskonflikten
Beachten Sie Folgendes:
- IADs0 unterstützt Func0 nicht.
- IADs1 unterstützt Func1 und Func0.
- IADs2 unterstützt Func2 und Func0.
Alle drei Schnittstellen sind duale Schnittstellen.
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
Beachten Sie, dass ein ADSI-Client einen IDispatch erkennt, der alle Dual- und Dispatchschnittstellen im Modell unterstützt, obwohl IADs1 Func2 nicht unterstützt. Daher kann der ADSI-Client Func2 mithilfe von myInf1.Func2 direkt aufrufen, ohne aufzulösen, welche Schnittstelle Func2 unterstützt.
myInf1.Func2
Sowohl IADs1 als auch IADs2 verfügen über eine Funktion namens Func0, aber IADs1::Func0 wird direkt mithilfe des vtable-Zugriffs aufgerufen, da beide der folgenden Funktionen für den Client gelten:
- Der Client verfügt über einen Zeiger auf das IADs1-Objekt mit dualer Schnittstelle, das über eine Funktion namens Func0 verfügt.
- Visual Basic unterstützt direkten vtable-Zugriff, vorausgesetzt, dass der Datentyp über die Typbibliothek verfügbar ist.
Im nächsten Codebeispiel verfügt der Client über einen Dual Interface-Zeiger auf IADs2 anstelle von IADs1. Daher wird IADs2::Func0 mithilfe des direkten vtable-Zugriffs aufgerufen.
Dim myInf2 as IADs2
Set myInf2 = myInf1 ' Query for pointer to IADs2
myInf2.Func0
Auch im nächsten Codebeispiel verfügen sowohl IADs1 als auch IADs2 über eine Funktion namens Func0, aber hier hat der Client einen Zeiger auf eine duale Schnittstelle, IADs0, die keine Funktion namens Func0 hat. Daher kann kein direkter vtable-Zugriff ausgeführt werden. Stattdessen werden IDispatch::GetIDsOfNames und Invoke aufgerufen, um Func0 aufzurufen.
Dim myInfNone as IADs0
Set myInfNone = myInf1 ' The aggregated object that
' supports IADs1 and IADs2.
myInfNone.Func0
Betrachten Sie diese beiden Fälle:
- IADs1 und IADs2 werden von zwei COM-Komponenten implementiert: Ext1 bzw. Ext2. Wenn Ext1 in der Registrierung vor Ext2 steht, wird IADs1::Func0 aufgerufen. Wenn Ext2 jedoch an erster Stelle in der Registrierung steht, wird IADs2::Func0 aufgerufen.
- Wenn IADs1 und ADs2 vom gleichen Erweiterungsobjekt implementiert werden, wird Func0 immer von den IADsExtension::P rivateGetIDsOfNames- und PrivateInvoke-Methoden der Erweiterung aufgerufen.
Der Erweiterungsentwickler muss bestimmen, wie Konflikte von Funktionen oder Eigenschaften verschiedener dualer IDispatch-Schnittstellen gelöst werden, die in einer Erweiterung den gleichen Namen aufweisen. Die Implementierung der Methoden IADsExtension::P rivateGetIDsOfNames und PrivateInvoke sollte diesen Konflikt lösen. Wenn Sie beispielsweise IMyInterface1::Func1 und IMyInterface2::Func1 verwenden, wobei IMyInterface1 und IMyInterface2 duale IDispatch-Schnittstellen sind, die vom gleichen Erweiterungsobjekt unterstützt werden. Die Methoden PrivateGetIDsOfNames und PrivateInvoke müssen bestimmen, welche Func1 immer aufgerufen werden soll.
Dasselbe gilt für in Konflikt geratene DISPIDs in verschiedenen Dual- oder IDispatch-Schnittstellen.
Beispielsweise ist die DISPID von IMyInterface1::Y in der Datei imyinterface1.odl oder imyinterface1.idl 2. Die DISPID von IMyInterface2::X ist auch 2 in iMyInterface2.odl. IADsExtension::P rivateGetIDsOfNames muss eine eindeutige DISPID innerhalb der Erweiterung selbst zurückgeben, anstatt für beide dieselbe DISPID zurückzugeben.
ADSI löst das erste Problem, indem nicht mehrere Schnittstellen mit in Konfliktstehenden Funktions- oder Eigenschaftsnamen unterstützt werden. Das zweite Problem wird behoben, indem den nicht verwendeten Bits der DISPID eine eindeutige Schnittstellennummer hinzugefügt wird, die sich innerhalb desselben Erweiterungsobjekts befindet.