簡體   English   中英

MEF +插件沒有更新

[英]MEF + Plug-In not updating

我已經在MEF Codeplex論壇上問了這個,但我還沒有得到回復,所以我想我會嘗試StackOverflow。 如果有人感興趣,這是原始帖子(這只是它的副本):

MEF Codeplex

“首先我要說的是,我對MEF完全不熟悉(今天才發現它),到目前為止我對此非常滿意。但是,我遇到了一個非常令人沮喪的問題。我正在創建一個應用程序,將有一個插件架構,插件將只存儲在一個DLL文件中(或編碼到主應用程序中。)DLL文件需要能夠在運行時重新編譯,應用程序應該識別這個並重新加載插件(我知道這很困難,但這是一個要求)。為了實現這個目的,我采取了http://blog.maartenballiauw.be/category/MEF.aspx的方法(尋找WebServerDirectoryCatalog)。基本上我的想法是“監視插件文件夾,將新的/修改過的程序集復制到Web應用程序的/ bin文件夾,並指示MEF從那里加載其導出。”這是我的代碼,這可能不是正確的方法,但它是我發現的在網周圍的一些樣本中:

        main()...
    string myExecName = Assembly.GetExecutingAssembly().Location;
        string myPath = System.IO.Path.GetDirectoryName(myExecName);
        catalog = new AggregateCatalog();
        pluginCatalog = new MyDirectoryCatalog(myPath + @"/Plugins");
        catalog.Catalogs.Add(pluginCatalog);


        exportContainer = new CompositionContainer(catalog);

        CompositionBatch compBatch = new CompositionBatch();
        compBatch.AddPart(this);
        compBatch.AddPart(catalog);
        exportContainer.Compose(compBatch);

    private FileSystemWatcher fileSystemWatcher;
    public DirectoryCatalog directoryCatalog;
    private string path;
    private string extension;

    public MyDirectoryCatalog(string path)
    {
        Initialize(path, "*.dll", "*.dll");
    }

    private void Initialize(string path, string extension, string modulePattern)
    {
        this.path = path;
        this.extension = extension;
        fileSystemWatcher = new FileSystemWatcher(path, modulePattern);
        fileSystemWatcher.Changed += new FileSystemEventHandler(fileSystemWatcher_Changed);
        fileSystemWatcher.Created += new FileSystemEventHandler(fileSystemWatcher_Created);
        fileSystemWatcher.Deleted += new FileSystemEventHandler(fileSystemWatcher_Deleted);
        fileSystemWatcher.Renamed += new RenamedEventHandler(fileSystemWatcher_Renamed);
        fileSystemWatcher.IncludeSubdirectories = false;
        fileSystemWatcher.EnableRaisingEvents = true;
        Refresh();
    }
    void fileSystemWatcher_Renamed(object sender, RenamedEventArgs e)
    {
        RemoveFromBin(e.OldName);
        Refresh();
    }
    void fileSystemWatcher_Deleted(object sender, FileSystemEventArgs e)
    {
        RemoveFromBin(e.Name);
        Refresh();
    }
    void fileSystemWatcher_Created(object sender, FileSystemEventArgs e)
    {
        Refresh();
    }
    void fileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
    {
        Refresh();
    }
    private void Refresh()
    {
        // Determine /bin path 
        string binPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins");
        string newPath = "";
        // Copy files to /bin 
        foreach (string file in Directory.GetFiles(path, extension, SearchOption.TopDirectoryOnly))
        {
            try
            {
                DirectoryInfo dInfo = new DirectoryInfo(binPath);
                DirectoryInfo[] dirs = dInfo.GetDirectories();
                int count = dirs.Count() + 1;
                newPath = binPath + "/" + count;
                DirectoryInfo dInfo2 = new DirectoryInfo(newPath);
                if (!dInfo2.Exists)
                    dInfo2.Create();

                File.Copy(file, System.IO.Path.Combine(newPath, System.IO.Path.GetFileName(file)), true);
            }
            catch
            {
                // Not that big deal... Blog readers will probably kill me for this bit of code :-) 
            }
        }
        // Create new directory catalog 
        directoryCatalog = new DirectoryCatalog(newPath, extension);
        directoryCatalog.Refresh();
    }
    public override IQueryable<ComposablePartDefinition> Parts
    {
        get { return directoryCatalog.Parts; }
    }
    private void RemoveFromBin(string name)
    {
        string binPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "");
        File.Delete(Path.Combine(binPath, name));
    }

所以這一切實際上都有效,並且在主要代碼結束后,我的IEnumerable變量實際上填充了DLL中的所有插件(如果您按照代碼位於Plugins / 1中,那么我可以修改dll中的插件文件夾)。 所以現在在這一點上,我應該能夠重新編譯插件DLL,將其放入Plugins文件夾,我的FileWatcher檢測到它已被更改,然后將其復制到文件夾“2”中,directoryCatalog應該指向新文件夾。 這一切實際上都有效! 問題是,即使看起來每個東西都指向正確的位置,我的IEnumerable變量也永遠不會使用新的插件進行更新。 如此接近,但到目前為止! 有什么建議? 我知道這樣做的缺點,沒有dll實際上是卸載並導致內存泄漏,但它是一個Windows應用程序,可能每天至少啟動一次,並且插件不太可能經常更改,但客戶仍然要求它在不重新加載應用程序的情況下執行此操作。 謝謝!

感謝你們所能提供的任何幫助,這讓我發瘋,無法解決這個問題。“

沒有重構的觸發器,因為您的目錄實現不提供通知。 實現INotifyComposablePartCatalogChanged來解決這個問題。

我相信MEF只能加載同一個程序集的一個版本(我嘗試使用Silverlight)

我遇到了類似的問題 - 在將發現的插件復制到應用程序的目錄后,即使在DirectoryCatalog上調用.refresh()之后,DirectoryCatalog也看不到它們。

我發現通過代碼解決了這個問題 - 我最好的猜測是文件系統仍然需要片刻,之后FileSystemWatcher啟動它的通知,然后MEF可以掃描新的程序集(可能完成一些模糊的復制操作)並查看里面的部件。

System.Threading.Thread.Sleep(1000),實際上很蹩腳,解決了這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM