我是在调用.NET对象还是COM对象?

Tim*_*ong 7 .net c# com-interop

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

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

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

objEarlyBound= (IMyInterface)objLateBound;

objEarlyBound.Method();
Run Code Online (Sandbox Code Playgroud)

如果我执行上面的代码,当objEarlyBound.Method()执行时,我是调用COM对象还是直接调用.NET对象?我怎样才能证明这种或那种方式?

Dan*_*ker 2

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

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

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

IMyInterface objEarlyBound = new MyClassExposedThroughCOM();
Run Code Online (Sandbox Code Playgroud)

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

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

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

实际上现在我想了一下,它不需要查询来找出这一点:它有一个之前生成的 CCW 全局表,因此它可以IUnknown在其中查找任何新的内容。COM 对象必须始终返回完全相同的地址,IUnknown以便可以将其用于对象身份比较。因此,CLR 始终可以识别它自己实现的 COM 对象,并获取相应的 CLR 对象。

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