默认 AppDomain 与新 AppDomain 中不同的依赖解析行为加载程序集

Posted

技术标签:

【中文标题】默认 AppDomain 与新 AppDomain 中不同的依赖解析行为加载程序集【英文标题】:Different dependency resolution behavior loading assembly in default AppDomain vs new AppDomain 【发布时间】:2015-09-10 05:11:59 【问题描述】:

我一直在研究与通过 C++/CLI 进行单元测试和托管/本机互操作相关的问题。细节并不重要,所以除非被问到,否则我不会填写,但情况可以提炼如下:

两个程序集,分别称为 Lib 和 Dep,存在于同一目录中,称为 D。Lib 通过程序集引用依赖于 Dep。我们正在一个应用程序中运行,该应用程序位于一个不同的、不相关的目录中。应用程序创建一个新的 AppDomain 并将 ApplicationBase 设置为目录 D,加载 Lib 程序集,并尝试通过反射在其中构造一个类型。

作为 Lib 的模块构造函数的一部分,我们转换到默认 AppDomain 并加载引用的程序集 Dep。因为默认AppDomain的ApplicationBase是NOT目录D,所以无法解析Dep,抛出FileNotFoundException异常,加载Lib程序集失败。

这一切都说得通——尽管可能令人费解,但我们试图加载一个不在当前 AppDomain 的程序集解析路径上的程序集,但失败了。

但是,如果我在默认 AppDomain 中运行整个过程而不是创建新的 AppDomain,则不会失败。即使目录 D 不是 ApplicationBase,也会加载 Lib 程序集,并且实例化其中一个类的代码可以正确运行。模块构造函数代码仍应在默认 AppDomain 中运行,尽管它不需要转换到它。

在我看来,第二个案例应该像第一个案例一样失败。这两种情况的程序集引用解析过程有什么不同?

【问题讨论】:

使用 Fuslogvw.exe 获得洞察力。记录所有绑定。 很好的建议,感谢您向我指出该实用程序。我会检查并报告。 我无法从 Fusion 日志中获得任何有用的信息。在成功或失败的情况下,Dep 程序集根本没有日志条目。 Lib 程序集的日志条目在成功案例中有一些内容,但在失败案例中,它似乎在过程的早期就失败了,可能是因为实际加载失败。虽然我希望至少能看到失败的程序集本身的一些东西,这本可以提供一些见解。 【参考方案1】:

好的,我通过比以前更完整地阅读the MSDN page "How the Runtime Locates Assemblies" 找到了我之前缺少的东西。最后一节“探测到的其他位置”概述了在解析正在加载的程序集的引用时,加载的程序集的位置被用作可以找到被引用程序集的位置的提示。

根据我看到的行为,我认为我们可以推断出提示信息是 AppDomain 特定的,因此在触发原始程序集加载的 AppDomain 之外不会考虑提示。

我用我的测试项目验证了这一点——如果引用的程序集没有切换到默认的 AppDomain,那么它会正确加载。所以这不是默认的 AppDomain 特殊行为,而是一般的 AppDomain 约束行为。

【讨论】:

以上是关于默认 AppDomain 与新 AppDomain 中不同的依赖解析行为加载程序集的主要内容,如果未能解决你的问题,请参考以下文章

.Net AppDomain详解

System.AppDomain类详解

卸载 appdomain 后程序集仍然存在

通过非默认 AppDomain 中的 C# 函数调用编组 C++ 指针接口

在默认 AppDomain 中的 Winforms 中托管 WPF 用户控件的弹出窗口中的选项卡导航损坏

如何将构造函数参数传递给 AppDomain.CreateInstanceXXX?