本文介绍了C# 暴露给 COM - 接口继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

例如:

[ComVisible(true), InterfaceType(ComInterfaceType.IsDual), Guid("XXXXXXX")]公共接口 IBaseClass{[保留签名]字符串 GetA()}[ComVisible(true), InterfaceType(ComInterfaceType.IsDual), Guid("XXXXXXX")]公共接口 IClass : IBaseClass{[保留签名]字符串 GetB()}[ComVisible(true), ClassInterface(ClassInterfaceType.None), Guid("XXXXXXX")]公共类 BaseClass : IBaseClass{公共字符串 GetA() { 返回A";}}[ComVisible(true), ClassInterface(ClassInterfaceType.None), Guid("XXXXXXX")]公共类类:BaseClass、IClass{公共字符串 GetB() { 返回B";}}

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

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

[奥德,uuid(XXXXXXXXXXXXXXXXXXXXX),版本(1.0),双重的,电子自动化,]接口 IClass : IDispatch {[id(0x60020000)]BSTR GetB();}

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

如果我去掉 IClass 从 IBaseClass 派生的地方,然后将方法添加到接口中,它就可以工作.

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

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

如果有人知道为什么会这样,或者有比复制粘贴到我的派生"界面更好的解决方法,请告诉我.如果没有,我会在几天内标记一个答案.

解决方案

这不是 .NET 问题,而是 COM 工作方式的结果.它不支持继承.您将在客户端修复此问题,它需要使用 IBaseClass 的 IID 调用 QueryInterface() 以获取指向 IBaseClass 接口的接口指针,以便它可以调用 GetA()..NET 互操作会自动提供一个 QI 实现来完成这项工作.但是,在这种情况下它不是很人性化,请设计您的 C# 端代码以方便客户端使用您的类,而不是相反.您通常需要一个单行重写方法,该方法委托给基本的 C# 类实现.

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

Say I have a class BaseClass that implements IBaseClass

Then I have an interface IClass that inherits IBaseClass.

Then I have a class named class that implements IClass.

For example:

[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"; }
}

When exposing to COM, if I make an instance of "Class" it does not allow me to call GetA().

When looking my IDL in the .tlb file, my IClass interface looks like:

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

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

It doesn't even look like IClass derives from IBaseClass!

If I take out where IClass derives from IBaseClass and just add the methods to the interface, it works.

How can I make C# enable this inheritance in COM? I'd rather not re-implement interfaces when I can inherit them.

CRAP: check this link .Net COM Limitation

If someone has an answer to why this is, or a better workaround than copy-paste to my "derived" interface, let me know. If not, I'll mark an answer in a couple days.

解决方案

This is not a .NET problem, it is a consequence of the way COM works. It doesn't support inheritance. You would fix this at the client side, it needs to call QueryInterface() with the IID for IBaseClass to get an interface pointer to the IBaseClass interface so it can call GetA(). .NET interop automatically provides a QI implementation that makes this work. However, it is not very user-friendly in this case, design your C# side code to make it easy for the client to use your class instead of the other way around. You'd typically need a one-liner override method that delegates to the base C# class implementation.

Note that there's a problem with your method signatures and the use of the [PreserveSig] attribute. They are not callable through IDispatch nor can they be auto-marshaled. That requires a method with a HRESULT as the return value type. It is automatic when you remove the attribute.

这篇关于C# 暴露给 COM - 接口继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 13:23