C#暴露给COM - 接口继承

jon*_*ers 12 .net c# com inheritance

假设我有一个实现IBaseClass的类BaseClass

然后我有一个继承IBaseClass的接口IClass.

然后我有一个名为class的类,它实现了IClass.

例如:

[ComVisible(true), InterfaceType(ComInterfaceType.IsDual), Guid("XXXXXXX")]
public interface IBaseClass
{
  [PreserveSig]
  string GetA()
}

[ComVisible(true), InterfaceType(ComInterfaceType.IsDual), Guid("XXXXXXX")]  
public interface IClass : IBaseClass
{
  [PreserveSig]
  string GetB()
}

[ComVisible(true), ClassInterface(ClassInterfaceType.None), Guid("XXXXXXX")]
public class BaseClass : IBaseClass
{
  public string GetA() { return "A"; }
}

[ComVisible(true), ClassInterface(ClassInterfaceType.None), Guid("XXXXXXX")]
public class Class : BaseClass, IClass
{
  public string GetB() { return "B"; }
}
Run Code Online (Sandbox Code Playgroud)

当暴露给COM时,如果我创建一个"Class"实例,它就不允许我调用GetA().

在.tlb文件中查找我的IDL时,我的IClass界面如下所示:

[
  odl,
  uuid(XXXXXXXXXXXXXXXXXXXXX),
  version(1.0),
  dual,
  oleautomation,

]
interface IClass : IDispatch {
    [id(0x60020000)]
    BSTR GetB();
}
Run Code Online (Sandbox Code Playgroud)

它甚至看起来像IClass派生自IBaseClass!

如果我拿出IClass从IBaseClass派生的地方,只是将方法添加到接口,它就可以工作.

如何让C#在COM中启用此继承?当我可以继承接口时,我宁愿不重新实现接口.

CRAP:检查此链接.Net COM限制

如果有人能够解答为什么会这样,或者更好的解决方法而不是复制粘贴到我的"派生"界面,请告诉我.如果没有,我会在几天内给出答案.

Han*_*ant 12

这不是.NET问题,它是COM工作方式的结果.它不支持继承.您可以在客户端修复此问题,它需要使用IBaseClass的IID调用QueryInterface()以获取指向IBaseClass接口的接口指针,以便它可以调用GetA()..NET interop自动提供一个QI实现,使其工作.但是,在这种情况下,它不是非常用户友好,设计您的C#端代码使客户端可以轻松使用您的类,而不是相反.您通常需要一个单行覆盖方法,该方法委托给基本C#类实现.

请注意,您的方法签名和[PreserveSig]属性的使用存在问题.它们不能通过IDispatch调用,也不能自动编组.这需要一个HRESULT作为返回值类型的方法.删除属性时会自动进行.

  • 恕我直言,这 ** 是 .net 问题,COM **完全** 支持 *接口*(不是类)继承,并且 regasm 可以生成一个 TLB,该 TLB 具有从 **ComVisible** IBaseClass 派生的 IClass。我注意到当这种情况发生时,Class 的 IDispatch 实现也不知道 IBaseClass 方法 - 非常令人失望。在一个 coclass 实现多个接口的情况下,您的建议 (QI) 很好;根据 Jonathan 链接中的 MVP,该技术不适用于继承 _hierarchy_,因为它根本不受支持。 (2认同)
  • @bacar - 一个很深的v-table很麻烦.它需要做多个不兼容的任务,支持接口方法指针以及类本身的虚方法.您无法控制指针的位置..NET类总是有虚方法,它继承System.Object.我不同意CLR可以更好地合成一组独立的v表,特别是对于COM客户端.但它没有发生,他们的目标是自动化.黑客IUnknown接口是可能的,只是不漂亮.无论如何没有类型库也没什么好看的. (2认同)

Shi*_*iji 6

这似乎与这个问题非常相似:C#中的ComVisible类中的接口继承

正如您在编辑中所指出的,这是对.com到COM跳的限制,COM接口不包含任何继承的接口.

在某些语言中,你可以通过在所有相关接口中包含一段代码来解决这个问题,但据我所知,这在C#中是不可能的.