问题描述
现在,我知道如果库在 .NET 中,通过 COM 访问它有点毫无意义,但是,我有点困惑,因为如果我要让某人编写一个库并通过它公开它COM,那个人应该可以用任何语言自由地这样做.
Now, I'm aware that if the library is in .NET, it's a little pointless to access it via COM, however, I am a bit perplexed because if I were to ask someone to write a library and expose it via COM, that person should be free to do so with any language.
COM 库是用哪种语言编写的对我来说并不重要,那么为什么重要呢?
It shouldn't matter to me which language that COM library is written in, so why does it matter?
作为参考,当您对从 .NET 库生成的 .tlb 文件使用 tlbimp 时会发生以下情况:
For reference, this is what happens when you use tlbimp on a .tlb file generated from a .NET library:
C:dev>tlbimp test.tlb
Microsoft (R) .NET Framework Type Library to Assembly Converter 4.0.30319.1
Copyright (C) Microsoft Corporation. All rights reserved.
TlbImp : error TI1029 : Type library 'test' was exported from
a CLR assembly and cannot be re-imported as a CLR assembly.
此外,我的测试 COM 库使用 IUnknown,仅支持早期绑定 COM 互操作.
Additionally, my test COM library uses IUnknown, supporting only early-bound COM interop.
推荐答案
tlbimp 只是问题的开始.
tlbimp is only the beginning of the problem.
每个 COM 可见的 .NET 对象都实现 IManagedObject.每次您尝试通过 COM 接口调用对象时,.NET 都会为 IManagedObject 执行 QueryInterface,如果成功,对象将被解包并直接访问.以这种方式消除互操作调用被认为是一种性能优化.
Every COM-visible .NET object implements IManagedObject. Every time you try to call an object through a COM interface, .NET does a QueryInterface for IManagedObject, and if it succeeds the object is unwrapped and accessed directly instead. Eliminating the interop call in this way is considered a performance optimization.
这在基于 COM 的互操作场景中是一个严重的问题,其中多个组件可以用 .NET 语言实现.如果每个 .NET 组件实现其自己的 tlbimp 生成的 COM 接口版本,它们将无法使用该接口相互通信.即使接口的每个 tlbimp 副本都具有相同的 COM GUID,.NET 仍将它们视为单独的接口.这个问题的正确"解决方案是在主互操作程序集中定义 COM 接口,并让每个 .NET 实现的组件使用相同的接口副本,但如果组件开发人员之间没有协调,这不太可能发生.
This is a serious issue in COM-based interop scenarios where multiple components may be implemented in .NET languages. If each .NET component implements its own tlbimp-generated version of the COM interface, they will be unable to communicate with each other using that interface. Even though each tlbimp'ed copy of the interface has the same COM GUID, .NET considers them separate interfaces. The "correct" solution to this problem is to define the COM interface in a primary interop assembly, and have every .NET-implemented component use that same copy of the interface, but if there's no coordination between component developers that's pretty unlikely to happen.
Microsoft 开发人员曾在 http://blogs.msdn.com/b/jmstall/archive/2009/07/09/icustomqueryinterface-and-clr-v4.aspx 以及 .NET 4 的解决方案,但它是基于预发布版本的,在最终版本中不起作用.我不知道微软在其他任何地方都承认它.
This problem was once highlighted by a Microsoft developer at http://blogs.msdn.com/b/jmstall/archive/2009/07/09/icustomqueryinterface-and-clr-v4.aspx along with a solution for .NET 4, but it was based on a pre-release version and doesn't work in the final. I'm not aware of anywhere else it's been acknowledged by Microsoft.
一种解决方案是放弃 .NET-to-.NET 场景中的接口,转而使用反射.这可能在许多情况下都有效,但性能当然不是很好.可能最好的解决方案是使用非托管代码来聚合每个托管组件并拒绝对 IManagedObject 的 QueryInterface 尝试.这与上述博客条目中的描述类似,但不依赖于不再像该博客中描述的那样工作的 .NET 功能.
One solution is to forego the interface in the .NET-to-.NET scenario and use reflection instead. This may work in many cases but of course isn't very performant. Possibly the best solution is to use unmanaged code to aggregate each of your managed components and reject attempts to QueryInterface for IManagedObject. This is similar to what's described in the above blog entry, but doesn't rely on .NET features that no longer work as described in that blog.
IMO 的 .NET 互操作行为非常糟糕,并且明显违反了 COM 规则(相同的 IID == 相同的接口,并且不必关心对象是用什么语言实现的).但是 .NET 从一开始就是这种行为方式,开发人员对此行为的反馈并没有改变 .NET 团队中任何人的想法.
The .NET interop behavior is, IMO, pretty terrible, and clearly violates COM rules (same IID == same interface, and shouldn't have to care what language the object is implemented in). But .NET has behaved this way from the beginning and no amount of feedback from developers bitten by this behavior has changed the minds of anyone on the .NET team.
这篇关于为什么不能通过 .NET 中的 COM 使用 .NET COM 库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!