现在,我从其ProgID加载类型并强制转换为强类型接口,如下所示:
IMyInterface objEarlyBound = null; Type t = Type.GetTypeFromProgID("My.ProgId"); objLateBound = Activator.CreateInstance(t); objEarlyBound= (IMyInterface)objLateBound; objEarlyBound.Method();
如果我执行上面的代码,当objEarlyBound.Method()执行时,我是调用COM对象还是直接调用.NET对象?我怎样才能证明这种或那种方式?
解决方法
objEarlyBound和objLateBound需要具有相同的标识,即==对它们将返回true.因此,从它们中的每一个,您总是可以获得另一个,并且同样支持它们支持的任何其他接口,并且如果您将它们中的任何一个分配给对象.但这并没有证明什么.
如果您直接引用包含通过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,其指向CCW,其指向CLR对象.通过使CLR引用直接指向CLR对象,可以清楚地简化这一点.
实际上现在我想一想,它不需要查询来找到它:它有一个它之前生成的CCW全局表,所以它可以在那里查找任何新的IUnknown. COM对象必须始终为IUnknown返回完全相同的地址,以便它可用于对象标识比较.因此,CLR始终可以识别它正在实现的COM对象,并获取相应的CLR对象.
顺便说一下,所有这些讨论都假设COM对象正在进行中.如果它是在进程外,那么情况就完全不同了;每个进程都有自己的CLR实例,因此也可以使用进程间编组的COM实现.