【问题标题】:Am I calling a .NET object or a COM object?我是在调用 .NET 对象还是 COM 对象?
【发布时间】:2010-03-05 08:21:37
【问题描述】:

今天出现了一个有趣的问题。假设我有一个 .NET 对象,它实现了某个接口 IMyInterface 并且也是 COM 可见的。

现在,我从其 ProgID 加载类型并转换为强类型接口,如下所示:

IMyInterface objEarlyBound = null;
Type t = Type.GetTypeFromProgID("My.ProgId");
objLateBound = Activator.CreateInstance(t);

objEarlyBound= (IMyInterface)objLateBound;

objEarlyBound.Method();

如果我执行上面的代码,当 objEarlyBound.Method() 执行时,我是调用 COM 对象还是直接调用 .NET 对象?我如何以一种或另一种方式证明这一点?

【问题讨论】:

    标签: c# .net com-interop


    【解决方案1】:

    RCW 应该是(据我所知)特殊类型 System.__ComObject,但是您可能想要调用Marshal.IsComObject,它会告诉您该对象是否是运行时包装器。在快速测试中,通过该路由创建的 COM 对象最终会成为直接托管对象并丢失 COM 包装器。

    【讨论】:

      【解决方案2】:

      无论哪种方式,您都无法证明太多 - 这是一个故意向您隐瞒的内部实现选择。

      objEarlyBoundobjLateBound 必须具有相同的身份,即== 将返回true。因此,您始终可以从它们中的每一个中获取另一个,并且对于它们支持的任何其他接口也是如此,并且如果您将它们中的任何一个分配给object。但这并不能证明什么。

      如果您直接引用了包含通过 COM 公开为 My.ProgId 的类的程序集,您可以说:

      IMyInterface objEarlyBound = new MyClassExposedThroughCOM();
      

      此时完全不需要 CLR 的 COM 支持。但随后您可以将该对象传递给某个外部 COM 库,此时 CLR 将创建一个 CCW 以与该对象关联。完成一次之后,对于任何给定的 CLR 对象,它总是可以返回到相同的 CCW。

      因此,为了将其与您的示例联系起来,您从 COM 对象周围的 RCW 开始,将其转换为接口,然后 CLR 可以(据我们所知)查询特殊的内部 COM 接口,如果找到,则允许它获取内部 CLR 对象,从而从那时起完全绕过 COM。如果在任何时候它需要回到 CCW,它可以这样做,因为它必须能够在向另一个方向工作时随时这样做。

      我尝试在手动实现的 C++ COM 对象的 QueryInterface 函数中放置断点,以查看 CLR 查询的内容。基本上它会尝试很多事情,其中​​一些我无法立即识别,因此它很可能是“嗅探”其他 CLR 对象。这样做是有道理的,以避免出现疯狂的 COM 三明治情况,其中 CLR 引用指向 RCW,而 RCW 指向 CCW,而 CCW 又指向 CLR 对象。这可以通过让 CLR 引用直接指向 CLR 对象来明显简化。

      其实我现在想想,它不需要查询就可以找到:它有一个以前生成的 CCW 全局表,所以它可以在那里查找任何新的IUnknown。 COM 对象必须始终为IUnknown 返回完全相同的地址,因此它可以用于对象身份比较。因此CLR总能识别出它自己实现的COM对象,并得到对应的CLR对象。

      顺便说一下,所有这些讨论都假设 COM 对象是在进程中的。如果它是进程外的,那么情况就完全不同了;每个进程都有自己的 CLR 实例,因此不妨使用进程间编组的 COM 实现。

      【讨论】:

      • 这很有趣,也很有帮助,谢谢。如果我从上面的示例中获取 objLateBound 并使用 objLateBound.InvokeMember("Method", ...) 调用它,我可以站在它的头上说,这会如何影响事情?那总是通过 CCW 调用,还是您仍然认为 CLR 可能足够聪明,可以嗅探 .NET 类并直接使用它?
      猜你喜欢
      • 2019-11-10
      • 2011-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-07
      • 2011-07-19
      • 2014-04-30
      相关资源
      最近更新 更多