2010-06-01 81 views
5

我想了解什麼是正確的,爲什麼要從C#代碼實現COM接口。當接口不從其他基本接口繼承時,它很簡單。像這樣的:如何在C#上聲明和實現COM接口,並從另一個COM接口繼承?

[ComImport, Guid("2047E320-F2A9-11CE-AE65-08002B2E1262"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IShellFolderViewCB 
{ 
    long MessageSFVCB(uint uMsg, int wParam, int lParam); 
} 

然而,事情開始的時候我需要實現與其他COM接口繼承的接口成爲weired。例如,如果我實現IPersistFolder2接口從IPersistFolderIPersist繼承,因爲我通常是在C#代碼繼承:

[ComImport, Guid("0000010c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IPersist 
{ 
    void GetClassID([Out] out Guid classID); 
} 

[ComImport, Guid("000214EA-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IPersistFolder : IPersist 
{ 
    void Initialize([In] IntPtr pidl); 
} 

[ComImport, Guid("1AC3D9F0-175C-11d1-95BE-00609797EA4F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IPersistFolder2 : IPersistFolder 
{ 
    void GetCurFolder([Out] out IntPtr ppidl); 
} 

操作系統是無法調用我的對象實現的方法。當我調試時,我可以看到我的IPersistFolder2實現的構造函數被多次調用,但是我實現的接口方法未被調用。我執行IPersistFolder2如下:

[Guid("A4603CDB-EC86-4E40-80FE-25D5F5FA467D")] 
public class PersistFolder: IPersistFolder2 
{ 
    void IPersistFolder2.GetClassID(ref Guid classID) { ... } 
    void IPersistFolder2.Initialize(IntPtr pidl) { ... } 
    void IPersistFolder2.GetCurFolder(out IntPtr ppidl) { ... } 
} 

什麼似乎很奇怪的是當我宣佈COM接口進口的追隨,它的工作原理:

[ComImport, Guid("0000010c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
internal interface IPersist 
{ 
    void GetClassID([Out] out Guid classID); 
} 

[ComImport, Guid("000214EA-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
internal interface IPersistFolder : IPersist 
{ 
    new void GetClassID([Out] out Guid classID); 
    void Initialize([In] IntPtr pidl); 
} 

[ComImport, Guid("1AC3D9F0-175C-11d1-95BE-00609797EA4F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
internal interface IPersistFolder2 : IPersistFolder 
{ 
    new void GetClassID([Out] out Guid classID); 
    new void Initialize([In] IntPtr pidl); 
    void GetCurFolder([Out] out IntPtr ppidl); 
} 

我不知道爲什麼它的工作原理,當我以這種方式聲明COM接口(使用new隱藏基本接口方法)。也許它與IUnknown的工作方式有關。有誰知道在C#中實現COM接口的正確方式是從其他COM接口繼承的,爲什麼?

+0

投票給你,告訴我如何「導入」IPersist。 http://stackoverflow.com/questions/1253368/c-get-progid-from-com-object使用它,但沒有提及如何添加引用。 – 2010-08-09 05:53:25

+0

我遇到了同樣的問題,並能夠使用'新'關鍵字修復它。 感謝@Hans Passant aswell :) – 2015-05-05 07:27:35

回答

3

與新的關鍵字整潔的把戲,這將確實解決問題。這裏的問題是COM不支持繼承。 IDL中的符號方便性使它看起來像它一樣。實際上,接口v-表必須聚合所有「繼承」的基礎接口。換句話說,對於IPersistFolder接口,它必須複製3個IUnknown方法和IPersist :: GetClassID方法的v表插槽。 CLR照顧IUnknown btw。

.NET構建的v表與此佈局不兼容,它不會複製基類方法插槽。