2013-11-26 29 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)。

相關問題