2

众所周知,.NET 程序集/类可以使COM 可见,因此程序集中的类可以由 COM 感知客户端实例化为 COM 对象。

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

4

2 回答 2

3

为什么是的,是的。

1) 需要这种互操作的特定情况是当您的类预计实现已经存在的 COM 接口时。例如,SharePoint 提供了一些插件架构,其中插件注册为实现一些自定义接口的 COM 类。

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

然而...

  • 很有可能,如果您尝试使用上述方法,客户端将成功创建您的类的 COM 对象实例,但在调用该类的任何方法时会崩溃。这是因为上面的方法打乱了接口中方法的顺序。因此客户端尝试调用需要一些参数的方法 A,但虚拟表中的条目(假设客户端是 C++)实际上调用方法 B!...并尝试将无效参数编组到其托管实现。
  • 有时翻译后的参数类型不正确(例如, abyte*可能翻译为 a ref byte)。
  • 有些接口只是翻译错误(特别是翻译后的 ILockBytes 包含RemoteReadAtandRemoteWriteAt方法,而不是ReadAtand WriteAt)。

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

2)按照文档ClassInterfaceAttribute中的建议,添加withClassInterfaceType.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)只是运行不会将.NET程序集添加到GAC中,因此如果您自己没有在GAC中安装程序集,请regasm.exe务必使用/codebase参数。regasm.exe

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

于 2012-07-03T19:32:33.707 回答
1

我遇到过的一对:

  1. COM 不支持泛型,因此通过 COM 访问的所有集合都需要无类型。
  2. 虽然 COM 支持接口继承,但 .Net 实现不支持。由于 COM 只关心接口,因此您可以在类中使用继承,但您的接口必须同时包含派生类和基类成员。
于 2012-07-03T19:44:58.320 回答