2009-10-24 65 views
1

這只是關於如何爲COM導入編寫代碼的問題。關於如何正確聲明互操作接口的說明

我的正確實施的互操作界面的理解是,主要標準是:

  1. 所有方法簽名必須以兼容的方式
  2. 方法必須準確顯示在相同的順序相匹配。 Net接口與非託管接口一樣
  3. 當非託管接口繼承自另一個非託管接口時,託管實現必須首先聲明基本級接口成員,從最底層接口開始。

我的問題是;如果我正在導入的接口從另一個接口繼承並覆蓋/隱藏基接口中的一個或多個成員,我該如何處理成員出現的順序?接口成員聲明去了哪裏?首先,基礎接口在哪裏聲明?或者從原來的位置移除並放置在派生接口聲明的位置?

[uuid(31d1c294-1dd2-11b2-be3a-c79230dca297)] 
interface BaseComInterface 
{ 
    void method1(); 
    void method2(); 
    void method3(); 
} 

[uuid(fab51c92-95c3-4468-b317-7de4d7588254)] 
interface DerivedComInterface : BaseComInterface 
{ 
    void method1(); 
    void method4(); 
    void method5(); 
} 

現在的C#代碼:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IDerivedComInterface 
{ 
    void method1(); // do I remove this one? 
    void method2(); 
    void method3(); 
    void method1(); // or this one? 
    void method4(); 
    void method5(); 
} 

回答

1

你有沒有一個真正在做這件事的人的例子?雖然在一個接口和另一個從它派生的接口中使用同一個方法的名稱在COM中是完全合法的,但它在幾乎所有的開發環境中使派生接口很難或不可能工作。這包括實現以及根據接口調用任何COM對象。

在COM接口中沒有重寫或隱藏的東西。 COM接口只是對象的二進制接口在內存中的佈局的約定,接口定義中的方法名稱除了工具之外沒有任何意義。在你的情況下,BaseComInterface承諾一個帶有六個方法的'vtable',前三個匹配IUnknown方法的簽名,接下來的三個匹配你給出的三個方法的簽名,所有這些都按正確的順序排列。另一方面,DerivedComInterface承諾包含九個方法的「vtable」,前三個簽名與IUnknown方法匹配,接下來的三個與BaseComInterface方法的簽名匹配,最後三個匹配DerivedComInterface特有的三個方法。這些方法的名稱是不重要的,除了您的IDE,工具和編譯器需要名稱來查找'vtable'指針。因此,基本上,在C#以及C,C++和其他一些語言中,爲了實現DerivedComInterface,需要對其中一個方法名進行裝飾以區分它的'vtable'插槽。

要回答你的問題 - 因爲它們都需要在那裏履行COM合同,你會刪除既不方法:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IDerivedComInterface 
{ 
    void method1(); 
    void method2(); 
    void method3(); 
    void method1_2(); //Decorated to distinguish from base interface method. 
    void method4(); 
    void method5(); 
} 

這忽略,如果這些接口從IDispatch接口而不是IUnknown的派生會發生什麼,一團糟,我不想進入。另外,請記住,如果您的idl確實將方法定義爲返回void,則必須使用PreserveSig屬性修飾您的C#方法。

+0

很好的答案,非常豐富,謝謝! – 2009-10-25 19:01:12

0

我建議你使用explicit interface member implementations避免衝突。

+0

我不認爲你讀了這個問題。我在這裏談論的是interop代碼,而不是純粹的託管繼承。 – 2009-10-24 21:01:49

+0

那你爲什麼要在C#中實現接口呢?界面由其他人實現。你只需要將COM對象的RCW強制轉換爲你想要的接口。 .Net會爲你調用QueryInterface。 – 2009-10-24 21:54:08