我遇到了一个问题,我认为这与CLR与COM对象的交互方式有关,但我希望这里的一些人可以提供更多的洞察力。我想提前为这个问题的模糊性道歉,遗憾的是我正在整合一个有点不透明的系统。
请考虑以下代码:
class Foo
{
private IComInterface comObject;
Foo(IServiceProvider provider)
{
this.comObject = serverProvider.GetService(typeof(ISomeService)) as IComInterface;
Debug.Assert(this.comObject != null); // comObject is *not* null here
}
void Bar()
{
IOtherComInterface otherInterface = this.comObject as IOtherComInterface;
Console.WriteLine(otherInterface == null);
}
}
COM互操作类型嵌入在我的程序集中,由另一个程序作为插件加载。当我第一次创建Foo
的实例时,服务提供者提供的COM对象(由程序提供)是非空的。但是,当我立即调用Bar()
时,转换为IComOtherInterface
不起作用:该方法打印“true”。
我的问题是,在加载了其他一些插件后,再次调用Bar()
会打印“false”。我已经验证它与Foo
的实例相同,实际上是comObject
的相同实例(我使用调试器标记了ID并且数字没有更改)。所以演员现在成功了。
所以我的问题是:这怎么可能?存储在comObject
中的对象是否有可能第二次通过同一个RCW包装新本机COM对象?是否有可能加载其他程序集以某种方式更改了IOtherComInterface
的类型标识,以便现在可以使用强制转换?其他一些我无法理解的疯狂可能性?
答案 0 :(得分:3)
COM对象在他们的公寓中“活着”,他们的代理也是如此。在公寓边界上传递“原始”COM接口指针(有时可能跨越线程边界读取)是使COM接口指针在没有访问冲突和其他方面崩溃仍然可操作的典型原因,但是在预期任务上失败,包括无法通过QueryInterface
返回另一个接口指针。
一旦有了COM接口指针,您就有兴趣在COM公寓和相应的线程中使用它,在那里获得指针。
要在公寓/线程之间传递指针,您需要采取其他步骤(将指针封送在原始线程上,然后在目标线程上解组)。另见: