C#暴露给COM - 接口继承

时间:2009-12-07 21:44:47

标签: c# .net inheritance com

假设我有一个实现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"; }
}

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

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

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

]
interface IClass : IDispatch {
    [id(0x60020000)]
    BSTR GetB();
}

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

如果我拿出IClass从IBaseClass派生的地方,只是将方法添加到界面,它就可以了。

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

CRAP:点击此链接.Net COM Limitation

如果某人有解答原因或更好的解决方法而不是复制粘贴到我的“派生”界面,请告诉我。如果没有,我会在几天内给出答案。

4 个答案:

答案 0 :(得分:12)

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

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

答案 1 :(得分:6)

这似乎与此问题非常相似:Interface inheritance in ComVisible classes in C#

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

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

答案 2 :(得分:0)

这是一种不同的方法,可以最大限度地减少工作量,并使界面保持干净 只需提供一个返回BaseInterface的附加属性:

public IBaseClass BaseProperties {
    get { return this; }
}

当然,您必须在IBaseClass接口中添加此部分:

public ISingleShot BaseProperties { get; }



这是相应的VB.Net代码:

ReadOnly Property BaseProperties As ISingleShot
Public ReadOnly Property BaseProperties As IBaseClass Implements IClass.BaseProperties
  Get
    Return Me
  End Get
End Property

答案 3 :(得分:0)

使用[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]作为扩展其他接口的接口的属性。 这是一种解决方法。