解決函式名稱衝突的範例

請考慮下列事項:

  • 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::GetIDsOfNamesInvoke 來叫用 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 rivateGetIDsOfNamesPrivateInvoke 方法叫用。

延伸模塊開發人員必須決定如何解決不同雙重 IDispatch 介面在延伸模組中具有相同名稱的函式或屬性衝突。 IADsExtension::P rivateGetIDsOfNamesPrivateInvoke 方法的實作應該能解決此問題。 例如,如果您使用 IMyInterface1::Func1 和 IMyInterface2::Func1,其中 IMyInterface1 和 IMyInterface2 是相同擴充物件支援的雙重 IDispatch 介面。 PrivateGetIDsOfNamesPrivateInvoke 方法必須判斷應該一律呼叫哪個 Func1。

這同樣適用於不同雙重或 IDispatch 介面中的衝突 DISPID。

例如,IMyInterface1::Y 的 DISPID 在 imyinterface1.odl 或 imyinterface1.idl 檔案中是 2。 IMyInterface2::X 的 DISPID 也是 iMyInterface2.odl 中的 2。 IADsExtension::P rivateGetIDsOfNames 必須針對每個傳回擴充功能本身內的唯一 DISPID,而不是針對兩者傳回相同的 DISPID。

ADSI 藉由不支援具有衝突函式或屬性名稱的多個介面來解決第一個問題。 它會藉由將唯一的 介面編號新增至 DISPID 未使用的位,藉此解決第二個問題。