【发布时间】:2011-08-09 15:08:49
【问题描述】:
我正在使用 COM 互操作从 VB6 应用程序调用托管代码,它本身随后在创建新的 AppDomain 后从另一个托管程序集调用代码。这个新的 AppDomain 是实际实例化正在使用的对象的实例。
为了使这更容易理解,以下是玩家:
- VB6 应用程序: LegacyApp.exe
- 包含在所有 .NET 程序集中使用的接口信息的程序集: MeatyInterfaces.dll
-
COM 互操作可见的 .NET 程序集: InteropAssembly.dll
- 此程序集直接引用 MeatyInterfaces.dll
-
InteropAssembly.dll 使用的程序集: MeatyImplementations.dll
- 此程序集直接引用 MeatyInterfaces.dll,并实现这些接口
- 通过实现“MeatyImplementations.ExampleImplementation”实现接口“MeatyInterfaces.IExampleInterface”
为了简化这个过程,本质上我们创建一个 AppDomain 并在 LegacyApp.exe 调用的 InteropAssembly.dll 代码中从新的 AppDomain 实例化 ExampleImplementation:
AppDomainSetup domainSetup = GetExampleSetupInfo();
AppDomain domain = AppDomain.CreateDomain(domainSetup.ApplicationName, AppDomain.CurrentDomain.Evidence, domainSetup);
ObjectHandle handle = domain.CreateInstance("MeatyImplementations.dll", "MeatyImplementations.ExampleImplementation");
一旦我们有了这个句柄,我们就会尝试解开它并将其转换为 IExampleInterface,ExampleImplementation 实现了它。
MeatyInterfaces.IExampleInterface initializer = (MeatyInterfaces.IExampleInterface) handle.Unwrap();
这会引发以下异常:
Exception: "System.InvalidCastException"
Message: "Unable to cast transparent proxy to type 'MeatyInterfaces.IExampleInterface'"
奇怪的是,如果我们运行这段确切的代码,但从托管 (.NET) 应用程序开始,它工作得非常好。
这是我所知道的:
- 我知道可以加载程序集的上下文有两种:Load 和 LoadFrom,后者对 DLL 的位置很敏感。
- 我知道将一个对象从一个加载上下文转换到另一个似乎是导致此问题的最常见原因(事实上,我能够找到的唯一一个相当详尽的搜索)
- 我知道,如果我按照此处的建议 (http://west-wind.com/weblog/posts/601200.aspx) 覆盖 AssemblyResolve 事件,它可以解决问题,这进一步向我表明(尽管我没有实质性证据)InteropAssembly.dll 必须加载 MeatyInterfaces.dll在与 MeatyImplementations.dll 以上述方式使用时不同的加载上下文中。
所以这是我不明白的......如果有人能提供澄清,我将不胜感激:
我不明白为什么加载上下文会有所不同,具体取决于我是通过 VB6 应用程序(使用 COM 互操作)还是 .NET 应用程序使用 InteropAssembly.dll,或者加载的整个概念是否Contexts 一直只是一个红鲱鱼,他的修复只是巧合地解决了我的问题。
【问题讨论】:
标签: .net com-interop appdomain