Freigeben über


Beispiel für das Auflösen von Funktionsnamenkonflikten

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 Dispatch-Schnittstellen im Modell unterstützt, obwohl IADs1 Func2 nicht unterstützt. Daher kann der ADSI-Client Func2 direkt mit myInf1.Func2 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 beides für den Client gilt:

  • Der Client verfügt über einen Zeiger auf das IADs1-Objekt der dualen Schnittstelle, das über eine Funktion namens Func0 verfügt.
  • Visual Basic unterstützt den direkten Vtable-Zugriff, vorausgesetzt, dieser Datentyp ist über die Typbibliothek verfügbar.

Im nächsten Codebeispiel verfügt der Client über einen dualen Schnittstellenzeiger 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

Im nächsten Codebeispiel verfügen sowohl IADs1 als auch IADs2 über eine Funktion namens Func0, aber hier verfügt der Client über 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 die folgenden 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 durch dasselbe Erweiterungsobjekt implementiert werden, wird Func0 immer von den Methoden IADsExtension::P rivateGetIDsOfNames und PrivateInvoke der Erweiterung aufgerufen.

Der Erweiterungsentwickler muss festlegen, wie Konflikte von Funktionen oder Eigenschaften verschiedener dualer IDispatch-Schnittstellen , die denselben Namen in einer Erweiterung haben, aufgelöst werden. Die Implementierung der Methoden IADsExtension::P rivateGetIDsOfNames und PrivateInvoke sollte diesen Konflikt beheben. Wenn Sie beispielsweise IMyInterface1::Func1 und IMyInterface2::Func1 verwenden, sind IMyInterface1 und IMyInterface2 duale IDispatch-Schnittstellen , die vom gleichen Erweiterungsobjekt unterstützt werden. Die Methoden PrivateGetIDsOfNames und PrivateInvoke müssen bestimmen, welcher Func1 immer aufgerufen werden soll.

Gleiches gilt für in Konflikt stehende DISPIDs in verschiedenen Dual- oder IDispatch-Schnittstellen .

Beispielsweise ist die DISPID von IMyInterface1::Y 2 in der Datei imyinterface1.odl oder imyinterface1.idl. Die DISPID von IMyInterface2::X ist auch 2 in iMyInterface2.odl. IADsExtension::P rivateGetIDsOfNames muss eine eindeutige DISPID innerhalb der Erweiterung selbst für jede zurückgeben, anstatt die gleiche DISPID für beide zurückzugeben.

ADSI löst das erste Problem, indem mehrere Schnittstellen mit in Konflikt stehenden Funktions- oder Eigenschaftsnamen nicht unterstützt werden. Das zweite Problem wird behoben, indem eine eindeutige Schnittstellennummer innerhalb desselben Erweiterungsobjekts zu den nicht verwendeten Bits der DISPID hinzugefügt wird.