【问题标题】:Are different Load Contexts used for referenced assemblies when calling a .NET assembly through COM/Interop vs. through a .NET Application?通过 COM/Interop 与通过 .NET 应用程序调用 .NET 程序集时,引用程序集是否使用不同的加载上下文?
【发布时间】: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


    【解决方案1】:

    我找到了答案:

    我看错了 Fusion Log:

    InteropAssembly.dll 在 LoadFrom 上下文中加载,但这不是问题。问题是当 InteropAssembly.dll 尝试加载 MeatyInterfaces.dll 时,它找不到它:MeatyInterfaces.dll 位于 InteropAssembly.dll 所在的 bin 文件夹中,但它没有在那里寻找它:它正在寻找在 LegacyApp.exe 的应用程序路径中。

    .NET 应用程序的工作基本上是巧合:这些程序集作为构建过程的一部分被添加到 .NET 应用程序的 bin 文件夹中,因此它在检查的文件夹中具有所需的所有依赖项。

    我看到的导致我走下加载上下文路径的异常基本上是一个巧合:加载依赖项失败直到第一次使用它时才触发异常,这恰好是发生强制转换的地方:这引发了一个异常,该异常似乎是在绝大多数情况下由不匹配的加载上下文引起的。

    F7U12

    是的,这就是原因:我现在学到了一个艰难的方法,尽管可以通过 COM 互操作从调用应用程序路径(或 GAC)以外的位置加载程序集,但程序集的依赖项仍然需要在应用程序的路径中。哦。

    【讨论】:

      猜你喜欢
      • 2018-05-21
      • 1970-01-01
      • 2012-01-01
      • 2010-10-17
      • 2012-05-18
      • 2018-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多