c# - 如何在 C# 上声明和实现一个继承自另一个 COM 接口(interface)的 COM 接口(interface)?

标签 c# com interop

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

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

然而,当我需要实现一个从其他 COM 接口(interface)继承的接口(interface)时,事情就开始变得奇怪了。例如,如果我实现继承自 IPersistFolderIPersistFolder2 接口(interface),它继承自 IPersist,就像我通常在 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 实现的构造函数被调用了很多次,但是我实现的接口(interface)方法没有被调用。我按如下方式实现 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 接口(interface)导入时,它起作用了:

[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 接口(interface)(使用 new 隐藏基本接口(interface)方法)时,我不知道为什么它会起作用。也许这与 IUnknown 的工作方式有关。有谁知道在 C# 中实现继承自其他 COM 接口(interface)的 COM 接口(interface)的正确方法是什么?为什么?

最佳答案

使用 new 关键字的妙招,确实可以解决问题。这里的问题是 COM 不支持继承。在 IDL 中使它看起来像它只是符号上的方便。实际上,接口(interface) v 表必须聚合所有“继承”的基础接口(interface)。换句话说,对于 IPersistFolder 接口(interface),它必须为 3 个 IUnknown 方法和 IPersist::GetClassID 方法复制 v 表槽。顺便说一句,CLR 会处理 IUnknown。

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

关于c# - 如何在 C# 上声明和实现一个继承自另一个 COM 接口(interface)的 COM 接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2952950/

相关文章:

c# - Windows Search sql - 无法访问 System.Search.QueryFocusedSummary

c# - Caliburn Micro - 文本框中的文本不会显示

c# - 如何使用 LINQ 将列表垂直拆分为 n 个部分

com - 从 COM 库传递对 COM 接口(interface)的引用

c# - C++ 调用托管 COM 对象找不到相关程序集

c++ - CoCreateInstance 失败,错误为 "System can not find the file specified"

c# - 如何在 MSI 安装程序中包含 pdb 文件以与应用程序的其余部分一起部署?

c# - TreeView 的子节点无法反射(reflect)绑定(bind)的变化

c# - 如何获取有关 IDispatch COM 接口(interface)故障的更多调试信息

c# - 如何处理返回结构体指针的方法?