2011-04-26 70 views
2

我正在构建一个需要从VBA引用的库,所以我需要提供一个类型库来支持早期绑定。我见过的大多数例子都定义了暴露给COM的类的接口,例如为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。我也看到了一些明确设置接口不匹配的例子 - 这样做有什么优势吗?

+1

关于为什么你需要一个接口和'ClassInterfaceType.None',请看这个问题http://stackoverflow.com/q/1435295/57428。 – sharptooth 2011-04-26 05:26:11

回答

5

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

这不会发生在后期绑定中,通常会有一个合理的诊断,如DISP_E_MEMBERNOTFOUND或DISP_E_BADPARAMCOUNT。这就是为什么微软很重视ComInterfaceType.InterfaceIsIDispatch。缺点是后期绑定很慢。另一个是只在运行时捕获错误,而不是编译时。

设置DispIDs非常少用。一些传统的微软产品使用了dispid绑定,将dispid预编译成代码。它大约是后期绑定的两倍,因为不需要IDispatch :: GetIDsOfNames()调用。你不太可能在野外遇到它们,当然不是任何VBA版本。

一个体面的KB文章is here主题。

+0

我看了文章 - 感谢指针。猜猜你是在谈论二进制兼容性 - 所以如果我安装一个新版本而不更新类型库,然后通过使用接口,实现COM接口的代码的vtable布局保持不变,函数调用仍然工作? – Shane 2011-04-26 14:10:49

+0

我对你关于重用IID的评论有点困惑。你是什​​么意思IID - 在我上面的例子中应用到接口的GUID?你是否在说,当你说“这本身就是犯罪”时,新版本的代码被释放时,应该改变界面上的GUID?这不会破坏版本之间的兼容性吗? – Shane 2011-04-26 14:11:27

+0

我想我知道你的意思是不重新使用IID--接口应该是不可变的,即一旦IID被分配给接口,它在组件的未来版本中不应该改变 - 只能添加新的接口。它是否正确? – Shane 2011-05-04 04:52:13

相关问题