【问题标题】:What is the advantage of defining an interface for .NET classes exposed to COM?为暴露给 COM 的 .NET 类定义接口有什么好处?
【发布时间】:2011-08-12 17:43:54
【问题描述】:

我正在构建一个需要从 VBA 引用的库,因此我需要提供一个类型库来支持早期绑定。我见过的大多数示例都为暴露给 COM 的类定义了一个接口,例如

[Guid("D6F88E95-8A27-4ae6-B6DE-0542A0FC7039")]     
[InterfaceType(ComInterfaceType.InterfaceIsDual)]     
public interface IMyClass 

[Guid("13FE32AD-4BF8-495f-AB4D-6C61BD463EA4")]     
[ClassInterface(ClassInterfaceType.None)]     
[ProgId("MyNamespace.MyClass")]     
public class MyClass : IMyClass

让一个类直接使用 ClassInterface.AutoDual 实现接口有什么缺点吗?对于更复杂的类,我喜欢使用接口来明确定义哪些成员是公开的 com,而不必在任何地方使用 ComVisible 属性。但是我也会有一些相当琐碎的数据类,比如事件参数,它们将完整地暴露给 COM。我还看到了在接口上明确设置 dispids 的示例 - 这样做有什么好处吗?

【问题讨论】:

标签: .net com


【解决方案1】:

是的,有一个大问题:DLL Hell 是讨厌的,具有早期绑定。 COM 客户端通过 v-table 指针直接调用该方法。如果使用相同接口 IID(这本身就是犯罪)的过时 COM 服务器是常驻的,那么这可能会调用错误或不存在的方法。运行时故障(通常是 AccessViolation)很难诊断。

延迟绑定不会发生这种情况,(通常)会有合理的诊断,例如 DISP_E_MEMBERNOTFOUND 或 DISP_E_BADPARAMCOUNT。这就是为什么微软非常喜欢 ComInterfaceType.InterfaceIsIDispatch。缺点是后期绑定很慢。另一个是错误只在运行时被捕获,而不是编译时。

设置 DispID 很少有用。一些旧版 Microsoft 产品使用 dispid 绑定,将 dispid 预编译到代码中。它的速度大约是后期绑定的两倍,因为不需要 IDispatch::GetIDsOfNames() 调用。您不太可能还会在野外遇到它们,当然不会是任何 VBA 版本。

关于主题is here 的一篇不错的知识库文章。

【讨论】:

  • 我阅读了这篇文章 - 感谢您的指点。猜猜你在谈论二进制兼容性 - 所以如果我安装一个新版本而不更新类型库,那么通过使用接口,实现 COM 接口的代码的 vtable 布局保持不变并且函数调用仍然有效?
  • 我对您关于重用 IID 的评论感到有些困惑。您所说的 IID 是什么意思 - 在我上面的示例中应用于接口的 GUID?当你说“这本身就是犯罪”时,你是说在发布新版本的代码时应该更改界面上的 GUID?这不会破坏版本之间的兼容性吗?
  • 我想我知道你所说的不重复使用 IID 是什么意思——接口应该是不可变的,即一旦 IID 被分配给一个接口,它就不应该在组件的未来版本中改变——只有新接口可以添加。这是正确的吗?
  • 我已经接受了你的回答,因为我猜它回答了我的问题,但我认为我的用例有点特殊。创建库的唯一目的是为 excel 提供功能——它确实需要支持 c++ 客户端(例如),这些客户端在编译时导入类型库并根据界面布局创建代码。需要了解更多信息,但我怀疑只要运行 excel 代码的机器具有兼容版本的程序集并且安装了它的类型库,一切都应该没问题——我认为没有存储有关二进制布局的信息在 .xls 文件中。
猜你喜欢
  • 2010-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
  • 2021-05-18
  • 2013-09-09
相关资源
最近更新 更多