簡體   English   中英

C#暴露給COM - 接口繼承

[英]C# exposing to COM - interface 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"; }
}

當暴露給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限制

如果有人能夠解答為什么會這樣,或者比將其復制粘貼到我的“派生”界面更好的解決方法,請告訴我。 如果沒有,我會在幾天內給出答案。

這不是.NET問題,它是COM工作方式的結果。 它不支持繼承。 您可以在客戶端修復此問題,它需要使用IBaseClass的IID調用QueryInterface()以獲取指向IBaseClass接口的接口指針,以便它可以調用GetA()。 .NET interop自動提供一個QI實現,使其工作。 但是,在這種情況下,它不是非常用戶友好,設計您的C#端代碼使客戶端可以輕松使用您的類而不是相反。 您通常需要一個單行覆蓋方法,該方法委托給基本C#類實現。

請注意,您的方法簽名和[PreserveSig]屬性的使用存在問題。 它們不能通過IDispatch調用,也不能自動編組。 這需要一個HRESULT作為返回值類型的方法。 刪除屬性時會自動進行。

這似乎與這個問題非常相似: C#中的ComVisible類中的接口繼承

正如您在編輯中所指出的,這是對.com到COM跳的限制,COM接口不包含任何繼承的接口。

在某些語言中,你可以通過在所有相關接口中包含一段代碼來解決這個問題,但據我所知,這在C#中是不可能的。

這是一種不同的方法,可以最大限度地減少工作量,並使界面保持干凈。
只需提供一個返回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

使用[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]作為擴展其他接口的接口的屬性。 這是一種解決方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM