2013-11-26 28 views
10

我有两个程序集:AppAddOnApp参考文献AddOn,但CopyLocal设置为false,因为AddOn将由App动态加载。为什么我需要一个已经加载的程序集的AssemblyResolve处理程序?

这里是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处理程序工作正常,但它似乎是一个黑客,我不明白为什么我需要它,因为它似乎在做一些微不足道的事情。

+1

你这样做是错误的。当你允许在你的程序中使用插件时,你*不知道插件中类的类型。它是由另一位程序员编写的。所以你应该对LoadFrom()的返回值很感兴趣,例如你可以使用Assembly.GetType()来发现一个类型。 –

+0

这是一个引用另一个插件的插件,因为它依赖于该功能。 – RobSiklos

+0

这不是一个插件,只是一个正常的相关程序集。您始终使用Copy Local = True来确保CLR可以自动查找组件,而无需您的帮助。这是默认设置。 –

回答

9

原因是有多个程序集加载上下文。程序集加载到的上下文影响它如何使用。当运行时使用默认探测机制加载程序集时,它将被放入所谓的Load上下文中。这是通过Assembly.Load加载程序集时使用的上下文。您已经使用自己的上下文使用LoadFrom加载了程序集。探测不会检查LoadFrom上下文,并且该文件不在探测路径中,因此您需要为运行时解析它。然而这不是对称的。如果程序集在加载上下文中加载,LoadFrom将首先从那里加载它(假设对于未签名的程序集,身份是相同的,路径是身份的一部分)。我会注意到有更多的上下文,包括ReflectionOnlyLoadReflectionOnlyLoadFromLoadFile加载没有上下文的程序集,即必须手动加载所有依赖项。

如果您想要在加载上下文中解析程序集,但是它们存在于应用程序的默认探测路径之外,那么也可以通过配置来完成。使用程序集绑定重定向的<codebase>元素或<probing>元素的privatePath属性。

阅读this了解更多信息。一段时间以来,Suzanne Cook也有一些博客文章重新讨论装配加载和上下文(请参阅here,herehere)。

相关问题