請考慮下列事項:
- IADs0 不支援 Func0。
- IADs1 支援 Func1 和 Func0。
- IADs2 支援 Func2 和 Func0。
這三個介面都是雙重介面。
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
請注意,即使 IADs1 不支援 Func2,ADSI 用戶端還是會辨識支援模型中所有雙重和分派介面的一個 IDispatch。 因此,ADSI 用戶端可以使用 myInf1.Func2 直接呼叫 Func2,而不需要解析哪個介面支援 Func2。
myInf1.Func2
IADs1 和 IADs2 都有一個名為 Func0 的函式,但 IADs1::Func0 是直接使用 vtable 存取來叫用,因為下列兩項都適用於用戶端:
- 用戶端具有雙介面 IADs1 物件的指標,該物件具有稱為 Func0 的函式。
- Visual Basic 支援直接 vtable 存取,假設數據類型可透過類型連結庫取得。
在下一個程式代碼範例中,用戶端具有IAD2的雙重介面指標,而不是 IADs1。 因此,使用直接 vtable 存取來叫用 IADs2::Func0。
Dim myInf2 as IADs2
Set myInf2 = myInf1 ' Query for pointer to IADs2
myInf2.Func0
同樣地,在下一個程式代碼範例中,IADs1 和 IADs2 都有一個名為 Func0 的函式,但在這裡,用戶端有雙介面 IADs0 的指標,其沒有稱為 Func0 的函式。 因此,無法執行任何直接的 Vtable 存取。 相反地,呼叫 IDispatch::GetIDsOfNames 和 Invoke 來叫用 Func0。
Dim myInfNone as IADs0
Set myInfNone = myInf1 ' The aggregated object that
' supports IADs1 and IADs2.
myInfNone.Func0
請考慮下列兩種情況:
- IADs1 和 IADs2 分別由兩個 COM 元件 Ext1 和 Ext2 實作。 如果 Ext1 位於登錄中的 Ext2 之前,則會叫用 IADs1::Func0。 不過,如果 Ext2 先出現在登錄中,則會叫用 IADs2::Func0。
- 如果 IADs1 和 ADs2 是由相同的擴充對象實作,則 Func0 一律由延伸模組的 IADsExtension::P rivateGetIDsOfNames 和 PrivateInvoke 方法叫用。
延伸模塊開發人員必須決定如何解決不同雙重 IDispatch 介面在延伸模組中具有相同名稱的函式或屬性衝突。 IADsExtension::P rivateGetIDsOfNames 和 PrivateInvoke 方法的實作應該能解決此問題。 例如,如果您使用 IMyInterface1::Func1 和 IMyInterface2::Func1,其中 IMyInterface1 和 IMyInterface2 是相同擴充物件支援的雙重 IDispatch 介面。 PrivateGetIDsOfNames 和 PrivateInvoke 方法必須判斷應該一律呼叫哪個 Func1。
這同樣適用於不同雙重或 IDispatch 介面中的衝突 DISPID。
例如,IMyInterface1::Y 的 DISPID 在 imyinterface1.odl 或 imyinterface1.idl 檔案中是 2。 IMyInterface2::X 的 DISPID 也是 iMyInterface2.odl 中的 2。 IADsExtension::P rivateGetIDsOfNames 必須針對每個傳回擴充功能本身內的唯一 DISPID,而不是針對兩者傳回相同的 DISPID。
ADSI 藉由不支援具有衝突函式或屬性名稱的多個介面來解決第一個問題。 它會藉由將唯一的 介面編號新增至 DISPID 未使用的位,藉此解決第二個問題。