一个COM/.NET互操作程序集能否与更新版本的COM组件一起使用?

3
我通过从COM DLL生成的Interop程序集,在C#项目中调用COM组件。COM接口已定义DispIds,我已验证这些在生成的Interop程序集中出现。
经过实验,如果我将COM组件升级到新版本,则Interop调用会出现严重错误(就像它正在调用错误的COM方法)。
这是否是预期的,即Interop程序集与为其生成的特定版本的COM接口密切绑定?我曾天真地认为只要DispIds和函数原型在新的COM组件中匹配,那么一切都会正常工作。
是否有一种方式告诉CLR在通过Interop程序集调用COM组件时使用DispIds,即某种形式的后期绑定? (我知道可以使用反射样式的C#代码进行后期绑定,但这比Interop程序集不太方便。)
2个回答

2
我发现了Brian Long的文章 .NET Interoperability: COM Interop

最常见的要求是使用早期绑定以获得编译时类型检查和对COM对象的直接(尽可能直接)vtable调用。上面的 [interop assembly] 示例采用了这种方法。

生成的互操作性程序集实现“直接vtable调用”,听起来似乎不适用于接口的新版本(除非新方法只添加到接口的末尾,即vtable的末尾?)。

也许有人可以证实或提供更完整的答案?


没错。但是你不应该在发布后改变一个接口,绝对不可以,甚至不能添加方法。一个常见的模式是定义另一个从先前接口继承的接口,在那里你可以定义新方法,保持先前接口的契约。 - acelent
@acelent 这取决于特定软件产品/项目/团队中“已发布”的定义。只分享内部事物应比向外部发送 DLL 作为最终产品具有更大的灵活性。 - StayOnTarget
@DaveInCaz,如果它以任何方式公开,比如在注册表中、类型库中或者在无需注册的COM互操作清单中,我认为它已经发布了。有许多内部的、私有的或未记录的接口,一些人最终弄清了它们的布局和目的,并将它们用于自己的场景,否则这些场景甚至更难实现。这种情况在知名组件和不再开发的组件中更常见。当然,您不必支持这种情况,但它往往会发生。 - acelent
@DaveInCaz,即使是内部使用,最佳实践也是不要重新定义接口。这样可以在同一台机器上测试两个不同版本的组件。这是支持多个版本组件场景的半途而废。 - acelent

2

当客户端程序员使用后期绑定时,DispIds才会被使用。如果这是你想让他做的,那么你必须强制执行。这很容易做到,在接口上应用[InterfaceType(ComInterfaceType.InterfaceIsDispatch)]属性即可。如果你只编写了一个类而没有编写接口,则给它加上[ClassInterface(ClassInterfceType.AutoDispatch)]属性。

客户端程序员任何尝试使用危险的早期绑定的行为现在都将失败,他必须编写后期绑定代码。不要指望能收到感谢信。

唯一的其他方法是删除你现在使用的[Guid]属性。这非常危险,让CLR自动生成guid,这样当你更改接口时,它将自动变为不同的值。客户端程序员会得到一个体面的E_NOINTERFACE错误,而不是调用完全错误的方法。嗯,不要指望能收到感谢信 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接