2013-04-22 66 views
10

MEF運行時插件更新問題

問題

我的MEF代碼在運行時沒有正確更新程序集,從與DirectoryCatalog關聯的文件夾中更新程序集。插件在運行時加載成功,但是當我更新dll並在DirectoryCatalog上調用Refresh時,程序集沒有得到更新。

背景

我正在構建一個具有MEF容器的dll,並使用DirectoryCatalog來查找本地插件文件夾。我目前從一個簡單的WinForm中調用這個dll,這是安裝到一個單獨的項目使用ShadowCopy,所以我可以覆蓋我的插件文件夾中的dll。我沒有使用FileWatcher來更新這個文件夾,而是公開一個調用DirectoryCatalog刷新的公共方法,所以我可以隨意更新程序集而不是自動更新。

代碼

基類實例化MEF目錄和容器,並將其保存爲類變量引用訪問後

public class FieldProcessor 
{ 
    private CompositionContainer _container; 
    private DirectoryCatalog dirCatalog; 

    public FieldProcessor() 
    { 
     var catalog = new AggregateCatalog(); 
     //Adds all the parts found in the same assembly as the TestPlugin class 
     catalog.Catalogs.Add(new AssemblyCatalog(typeof(TestPlugin).Assembly)); 
     dirCatalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory + "Plugin\\"); 
     catalog.Catalogs.Add(dirCatalog); 

     //Create the CompositionContainer with the parts in the catalog 
     _container = new CompositionContainer(catalog); 
    } 

    public void refreshCatalog() 
    { 
     dirCatalog.Refresh(); 
    } 

} ... 

這裏就是我試圖覆蓋插件。我的更新測試是將返回的響應輸出到一個文本框,我更改插件返回的字符串,重建並將其複製到插件文件夾中。但它不會更新正在運行的應用程序,直到我關閉並重新啓動應用程序。

[Export(typeof(IPlugin))] 
[ExportMetadata("PluginName", "TestPlugin2")] 
public class TestPlugin2 : IPlugin 
{ 
    public IEnumerable<IField> GetFields(ContextObject contextObject, params string[] parameters) 
    { 
     List<IField> retList = new List<IField>(); 
     //Do Work Return Wrok Results 
     retList.Add(new Field("plugin.TestPlugin2", "TestPluginReturnValue2")); 
     return retList; 
    } 
} 

編輯

import語句

[ImportMany(AllowRecomposition=true)] 
    IEnumerable<Lazy<IPlugin, IPluginData>> plugins; 

研究

我在文章和代碼示例的答案似乎是做了相當廣泛的研究和無處不在,一個DirectoryCatalog添加到容器中,並保存該目錄的引用,然後在該引用上調用Refresh,在添加了新插件後,它將更新程序集......我正在執行這些程序集,但它沒有顯示來自新插件dll的更新輸出。

請求

有沒有人看過這個問題,或者知道什麼可能會導致我的問題,在運行時不更新的程序集?任何額外的信息或見解,將不勝感激。

決議

感謝Panos和Stumpy爲他們的鏈接,這導致我的解決方案我的問題。對於未來的知識搜索者,我的主要問題是,當新程序集與覆蓋的dll具有完全相同的程序集名稱時,Refresh方法不會更新程序集。對於我的POC,我只是測試了重新生成日期附加到程序集名稱和其他一切相同,它的工作就像一個魅力。他們在下面的評論中的鏈接非常有用,如果你有同樣的問題,建議你這樣做。

+1

DirectoryCatalog.Refresh會沒有檢測到更新的assebmlies。只有新的或刪除的。看看這個答案解決方法和建議:http://stackoverflow.com/a/14842417/850119 – 2013-04-23 10:14:32

+0

我的dll被鎖定時,他們被加載,所以我不能用新的dll覆蓋它們。你沒有這個問題嗎?你做了什麼讓他們可以更新。 – 2013-12-18 11:18:55

+0

是的,我確實有這個問題。我提到的其中一個步驟是啓用「Shadow Copy」。陰影複製允許程序拉取dll程序集的本地副本,並將它們添加到本地緩存中,而不是鎖定dll。必須啓用此功能才能在運行時「熱插拔」dll,否則您需要停止該程序,更改dll,然後重新啓動它。我認爲這是我看的例子,但如果它不適合你谷歌MEF和影子副本,http://stackoverflow.com/questions/12593308/mef-and-shadowcopying-dlls-so-that-i -can-over-them-at-runtime – Madullah 2014-02-04 01:36:51

回答

3

您是否爲您的Import attribut設置了AllowRecomposition參數?

AllowRecomposition 
Gets or sets a value that indicates whether the property or field will be recomposed when exports with a matching contract have changed in the container. 

http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.importattribute(v=vs.95).aspx

編輯:

DirectoryCatalog不更新組件,只有添加或刪除: http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.hosting.directorycatalog.refresh.aspx

對周圍的工作: https://stackoverflow.com/a/14842417/2215320

+0

我做到了,對不起,我原本沒有發佈import語句代碼,我已經更新了問題以反映我的import語句。 – Madullah 2013-04-23 13:33:04

+0

和你的刷新代碼?我認爲問題在裏面。你說沒有使用FileSystemWatcher,你如何檢測並重新加載你的程序集? – Niels 2013-04-23 17:56:41

+0

我通過上面看到的RefreshCatalog方法公開它。我從winForm上的按鈕單擊事件調用該方法。 – Madullah 2013-04-23 19:12:12