【问题标题】:Add path to Current AppDomain添加当前 AppDomain 的路径
【发布时间】:2015-08-20 11:50:00
【问题描述】:
我有两个完全不同的目录。目录 1 包含我的应用程序,目录 2 包含很少的程序集。在应用程序启动的运行时,我将加载程序集。默认情况下,执行程序集的 AppDomain 将发现目录 1(应用程序文件夹)或 GAC 中的程序集。如果文件不存在,我们将收到错误消息。但我还必须扩展 AppDomain 的搜索目录以在 Directory 2 中搜索。也就是说,AppDomain 将搜索 Directory1(本地 bin),然后是 GAC,然后是其他默认值,最后在 Directory 2 中搜索。
我试过了:
1.通过设置PrivateBinPath,但仅限于ApplicationBaseDirectory内。
2.通过AssemblyResolve,但不直接引用。 AssemblyResolve 代码也永远不会命中。
【问题讨论】:
标签:
appdomain
appdomainsetup
【解决方案1】:
使用AssemblyResolve 事件通常是正确的方法。如果它永远不会被击中,它可能注定为时已晚。例如,当 CLR 遇到一个方法时,它将完全编译它,解析它的所有引用。如果这样的决议失败,它将永远失败。如果您在任何或所有程序集绑定失败之后绑定AssemblyResolve 事件,则该事件将永远不会命中。
要解决此问题,请确保尽早绑定 AssemblyResolve 事件。在可执行文件中,这很容易(首先在您的应用程序的入口点,或您在那里使用的任何类型的cctor)。在库中,这可能更难,最佳实践方法是使用模块初始化程序,它在加载模块时运行(大多数程序集包含一个模块)。
由于模块初始化程序无法通过 C# 或我所知道的任何其他 .NET 语言设置,因此您必须求助于方法编织。我个人喜欢 Fody,事实证明,有一个名为 Fody Module Init 的预定义 Fody 包就是为了这个东西。
只需在您的库中公开放置以下代码:
public static class ModuleInitializer
{
public static void Initialize()
{
// bind to the CurrentDomain.AssemblyResolve event
}
}
Fody 也适用于其他语言(您无需指定使用哪种语言),但您必须手动创建静态 ModuleInitializer 类。
使用这种方法,您可以确定对于 CLR 的 Fusion 无法自行找到的任何程序集调用 AssemblyResolve 事件。