如何在inheritance自另一个COM接口的C#上声明和实现COM接口?

我试图了解从C#代码实现COM接口的正确原因是什么。 当接口不从其他基接口inheritance时,它很简单。 像这个:

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

然而,当我需要实现从其他COM接口inheritance的接口时,事情开始变得疲惫不堪。 例如,如果我实现inheritance自IPersistFolderIPersistFolder2接口,它通常依赖于C#代码从IPersistFolderinheritance:

 [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#中实现inheritance自其他COM接口的COM接口的正确方法是什么?为什么?

使用new关键字的巧妙技巧,确实可以解决问题。 这里的问题是COM不支持inheritance。 在IDL中仅仅是符号的方便使它看起来像它。 实际上,接口v表必须聚合所有“inheritance的”基接口。 换句话说,对于IPersistFolder接口,它必须复制3个IUnknown方法和IPersist :: GetClassID方法的v表槽。 CLR负责IUnknown btw。

.NET构建的v表与此布局不兼容,它不复制基类方法槽。