2009-09-26 84 views
0

我有一段.NET代码,由于各种原因(可靠性,部署)必须在单独的AppDomain中运行。我创建了一个派生自MBR的代理对象,它将调用委托给实际的东西,所以它不会加载到当前的AppDomain中。我通过通常的CreateInstanceAndUnwrap创建代理。从COM互操作失败使用AppDomain

this.eDirectCommunication = (EDirectCommunicationProxy) this.appDomain.CreateInstanceAndUnwrap(x, y); 

这个伟大的工程,当我使用它从一个.NET客户端,从COM客户端转换失败加载然而,当。我无法从透明代理投射。我验证了需要的类型是在所需的AppDomain上创建的,并且Unwrap成功,只是转换失败。有趣的是,它在两个AppDomain具有相同的基本目录时工作,这指向程序集绑定失败。但Fusion日志查看器没有提到任何问题。

有两个有点类似的问题herehere,但他们没有提供答案。 任何想法出了什么问题,或者我该如何进一步调试?

回答

1

几年前我遇到了这个确切的问题。 IIRC,问题在于调用堆栈跨越两个appdomain边界,这导致代理到被管对象被编组两次(COM-> default-> yours:new object: - > yours-> default)。通常不是问题,但有一个特殊的接口,.NET COM封送器QI为此说“嗨,我是一个托管对象,需要特殊的编组行为”(对不起,不记得IID-尝试ComTrace或将您的自己的IDispatch impl并通过CLR编组来查看)。当你在默认域中运行时,它会知道你被管理,然后请求并尝试加载你的托管类型,只有当你的新域的basedir与默认相同时,它才会成功。这显然打败了整个目的。

我已经处理了几种方法。一种方法是将对象创建为异步,以便我可以将托管代理直接推送到新域中的非托管代码(例如,注册非托管回调,并直接从新域调用它,绕过默认域)。这在添加场景中显然非常棘手,您无法控制端到端的所有内容。

另一个是有一小块非托管代码,当.NET平台处理器问“你真的是一个托管对象吗?但是会通过所有其他QIs以及IDispatch上的所有内容而不受干扰(我仅限于使用IDispatch,这使得它更容易)。所以新的序列变为:COM-> default-> yours:new object-> new proxy wrapper-> default-> COM。

主要PITA-我在CLR互操作团队中发现了一篇博客文章,该文章在未来的CLR发布中为此悬浮了一些可能的修复方法,但这是几年前的事,我不记得是谁(对不起,我不再为了生活而互助了,谢天谢地!)