我有两个程序集:App
和AddOn
。 App
引用AddOn
,但CopyLocal
设置为false
,因为AddOn
将App
动态加载。
以下是AddOn
中的代码:
namespace AddOn
{
public class AddOnClass
{
public static void DoAddOnStuff()
{
Console.WriteLine("AddOn is doing stuff.");
}
}
}
以下是App
中的代码:
class Program
{
static void Main(string[] args)
{
Assembly.LoadFrom(@"..\..\..\AddOn\bin\Debug\AddOn.dll");
// Without this event handler, we get a FileNotFoundException.
// AppDomain.CurrentDomain.AssemblyResolve += (sender, e) =>
// {
// return AppDomain.CurrentDomain.GetAssemblies()
// .FirstOrDefault(a => a.FullName == e.Name);
//};
CallAddOn();
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void CallAddOn()
{
AddOnClass.DoAddOnStuff();
}
}
我不明白为什么代码不能与AssemblyResolve
中评论的Main()
处理程序一起使用。在Visual Studio中运行时,调试器会在CallAddOn()
上使用FileNotFoundException
中断。为什么抱怨?程序集已加载,它与App
引用的版本完全相同(即磁盘上的文件相同)。
我觉得有一些基本概念,我在这里不能正确理解。评论AssemblyResolve
处理程序工作正常,但它似乎是一个黑客,我不明白为什么我需要它,因为它似乎做了一些微不足道的事情。
答案 0 :(得分:9)
原因是有多个程序集加载上下文。加载程序集的上下文会影响它的使用方式。当运行时使用默认探测机制加载程序集时,它将被置于所谓的Load上下文中。这是通过Assembly.Load
加载程序集时使用的上下文。您已使用LoadFrom
加载程序集,LoadFrom
使用自己的上下文。探测不会检查LoadFrom上下文,并且文件不在探测路径中,因此您需要为运行时解析它。然而,这不是对称的。如果在Load上下文中加载了程序集,ReflectionOnlyLoad
将首先从那里加载它(假设标识是相同的。对于无符号程序集,路径是标识的一部分。)。我会注意到有更多的上下文,包括ReflectionOnlyLoadFrom
和LoadFile
。 privatePath
加载没有上下文的程序集,即必须手动加载所有依赖项。
如果希望在Load上下文中解析程序集,但是它们存在于应用程序的默认探测路径之外,您也可以通过配置来执行它。使用程序集绑定重定向的<codebase>
元素或<probing>
元素的{{1}}属性。
阅读this了解详情。 Suzanne Cook还提供了一些博客文章,其中包括装配加载和上下文(请参阅here,here和here)。