在.NET类中实现COM接口时是否存在“陷阱”?

时间:2012-07-03 19:32:33

标签: .net com com-interop

已知.NET程序集/类可以成为COM Visible,因此可以通过支持COM的客户端将程序集中的类实例化为COM对象。

是否有任何'陷阱'需要注意?

2 个答案:

答案 0 :(得分:3)

为什么是,是的。

1)需要这种Interop的特定情况是,您的类应该实现已经存在的COM接口。例如,SharePoint提供了一些插件体系结构,其中插件注册为实现某些自定义界面的COM类。

如果接口没有Primary Interop Assembly,则需要添加对TLB或包含TLB的DLL的引用。通过在添加引用时选择“浏览”,可以在Visual Studio中添加引用。如果你没有TLB,你应该有一个IDL,你可以使用midl.exe编译成TLB。一些文档建议等效地在TLB上运行tlbimp.exe并添加对生成的程序集的引用。

...然而

  • 很可能,如果您尝试使用上述方法,客户端将成功创建您的类的COM对象实例,但在调用其上的任何方法时将崩溃。这是因为上述方法会破坏界面中方法的顺序。因此客户端尝试调用方法A,它需要一些参数,但虚拟表中的条目(假设客户端是C ++)实际上调用方法B!...并尝试将无效参数封送到其托管实现。
  • 有时,已翻译的参数类型不正确(例如,byte*可能会转换为ref byte)。
  • 某些界面的翻译错误(特别是翻译的ILockBytes包含RemoteReadAtRemoteWriteAt方法,而不是ReadAtWriteAt)。

因此,虽然可以使用从TLB自动生成的程序集作为起点 - 您必须通过修改程序集或仅将生成的代码复制到源文件来修复上述所有问题然后进行必要的更改。

2)根据documentation中的建议添加ClassInterfaceAttribute ClassInterfaceType.None作为类型。

3)为Any CPU架构构建程序集,然后在要注册它的任何机器上构建 -

  • 如果要通过32位进程注册程序集以进行COM使用,请使用C:\Windows\Microsoft .NET\Framework\<version>\regasm.exe进行注册。
  • 如果要通过64位进程注册程序集以供COM使用,请使用C:\Windows\Microsoft .NET\Framework64\<version>\regasm.exe进行注册。

4)仅运行regasm.exe不会将.NET程序集添加到GAC,因此如果不安装程序集,请务必使用/codebase regasm.exe参数在GAC中自己。

5)即使Visual Studio以管理员权限运行,如果您在构建选项中选中“注册COM互操作”复选框,则程序集的注册通常会失败。最好清除复选框,而是将regasm.exe添加为后期构建事件。

答案 1 :(得分:1)

我遇到的一对夫妇:

  1. COM不支持泛型,因此通过COM访问的所有集合都需要进行无类型处理。
  2. 虽然COM支持接口继承,但.Net实现却没有。由于COM只涉及接口,因此可以在类中使用继承,但接口必须包含派生类和基类成员。