2012-10-31 63 views
0

我有一個應用程序通過MEF加載插件。MEF程序集從緩存中加載?

應用程序正在終端服務器上的多個實例中運行。

當我需要在生產環境中測試新插件時,我將MEF重定向到另一個文件夾。 問題是,即使在重定向之後,組件也會從原始文件夾加載。 它不會每次都發生,我無法在我的機器上重現它。我懷疑這是某種緩存問題。

的MEF加載代碼看起來是這樣的:

using (var catalog = new AggregateCatalog()) { 

    Console.WriteLine("Loading components from {0}", folder); 

    catalog.Catalogs.Add(new DirectoryCatalog(folder, "*.dll")); 

    using (var container = new CompositionContainer(catalog)) { 
     try { 
      container.ComposeParts(this); 
     } 
     catch (ReflectionTypeLoadException ex) { 
      foreach (var loaderException in ex.LoaderExceptions) { 
       // log loading error 
    } 
} 

foreach (var assembly in _allComponents.GroupBy(x => x.GetType().Assembly)) { 
    Console.WriteLine("Loaded from {0}", assembly.Key.CodeBase); 
} 

從代碼的結果是上面的樣子

Loading components from C:\NewPlugins 
Loaded from C:\OldPlugins 
+0

難道你在兩個目錄中都有相同標識的程序集嗎?如果是這樣,只需創建一個插件更新,就可以使您的程序集具有強大的名稱並增加版本。 –

+0

是的,當然他們有相同的身份。如果這是問題,我認爲'DirectoryCatalog'是一個壞名字,因爲它通過身份加載程序集,而不是從目錄加載。 – adrianm

回答

0

因爲,根據您的意見,您有與兩個目錄組件相同的身份,上面代碼的輸出是正常的。這不是DirectoryCatalog的問題。它會嘗試從特定目錄加載程序集,但如果具有相同標識的程序集已加載到當前的AppDomain中,則CLR將不加載該程序集。從集會的地點來看,無關緊要,重要的是身份。

解決的辦法是讓你的程序集有強大的名字,並在創建插件更新時增加版本。這樣,NewPlugins目錄中的程序集將具有與已從OldPlugins目錄中加載的目錄不同的身份。

如果您有興趣瞭解如何加載程序集,請查看有關程序集加載的Suzanne Cook's blog條目。

+0

我知道程序集是如何加載的。正如你所說,我的解釋是,CLR只考慮加載在相同appdomain中的程序集的身份(因此無法加載具有相同身份的兩個不同程序集)。 OldPlugins中的程序集僅由同一臺計算機上完全不同的應用程序加載,因此顯然身份查找是跨應用程序域。 (仍然認爲這是DirectoryCatalog的問題,它應該強制從目錄加載) – adrianm

+0

@adrianm使用Assembly.LoadFile可以從不同位置加載具有相同身份的兩個程序集。但DirectoryCatalog使用Assembly.Load(AssemblyName)。 CLR加載程序集的方式非常複雜。每當我讀到它,似乎我第一次理解了一些東西。我不確定你對不同應用程序的含義。我以爲你試圖在同一AppDomain上加載兩個版本。您是否使用gacutil在GAC上安裝這些程序集? –

+0

我在OldPlugins文件夾中的服務器上運行了一個應用程序實例。現在我將更新版本的應用程序和/或插件放在同一臺服務器上的NewPlugins文件夾中(例如測試新功能)。當我啓動更新的應用程序時,它仍然從OldPlugins文件夾加載程序集。沒有涉及GAC。我只是將DirectoryCatalog指向應用程序的啓動文件夾。 – adrianm