簡體   English   中英

MEF和ShadowCopying DLL,以便我可以在運行時覆蓋它們

[英]MEF and ShadowCopying DLLs so that I can overwrite them at runtime

我試圖阻止我的應用程序鎖定我的MEF插件目錄中的DLL,以便我可以在運行時覆蓋程序集(注意我實際上並沒有嘗試讓MEF在運行時重新加載它們,在下一個應用程序啟動很好,我只是不想要停止應用程序來復制)

我試圖通過為我的mef加載的程序集創建一個陰影復制的應用程序域來執行此操作,如下所示:

[Serializable]
    public class Composer:IComposer
    {
        private readonly string _pluginPath;
        public Composer(IConfigurePluginDirectory pluginDirectoryConfig)
        {
            _pluginPath = pluginDirectoryConfig.Path;
            var setup = new AppDomainSetup();
            setup.ShadowCopyFiles = "true"; // really??? is bool not good enough for you?
            var appDomain = AppDomain.CreateDomain(AppDomain.CurrentDomain.FriendlyName + "_PluginDomain", AppDomain.CurrentDomain.Evidence, setup);

            appDomain.DoCallBack(new CrossAppDomainDelegate(DoWorkInShadowCopiedDomain));      
        }

        private void DoWorkInShadowCopiedDomain()
        {
            // This work will happen in the shadow copied AppDomain.

            var catalog = new AggregateCatalog();
            var dc = new DirectoryCatalog(_pluginPath);
            catalog.Catalogs.Add(dc);
            Container = new CompositionContainer(catalog);
        }

        public CompositionContainer Container { get; private set; }
    }

然后通過此類上的CompositionContainer訪問我的MEF組件目錄。 但是,組合容器似乎只在shadowcopy域內初始化(這是有意義的),這意味着它在我的應用程序域中為null。 我只是想知道是否有更好的方法來做這個或某種方式跨域查詢來獲取我的MEF組件

如果您不想遵循Dan Bryant和zync的解決方案,您可以創建一個shell應用程序,只需在新的AppDomain執行您的應用程序。

一種方法是:

  1. 創建一個新的應用程序項目,它將是shell應用程序。
  2. 在shell應用程序中,創建AppDomain ,啟用卷影復制,如果需要,請指定啟用卷影復制的目錄。
  3. 使用AppDomain.ExecuteAssembly來調用當前的應用程序。

如果您擁有類庫而不是應用程序,則可以嘗試以下操作:

  1. 創建一個新的類庫項目。
  2. 將以下接口添加到新的類庫項目:

     public interface IRemoteLoader { void Load(); void Unload(); } 
  3. 將此接口的實現添加到需要在新AppDomain中執行的類庫中。 LoadUnload方法中,您應該添加代碼以分別執行初始化和清理。 使類派生自MarshalByRefObject 這是.NET Remoting在兩個AppDomain上創建代理對象所必需的。

  4. 在創建新的AppDomain之后,使用CreateInstanceAndUnwrap從步驟3創建loader類的實例。

  5. 使用從步驟4創建的對象LoadUnload

如果你沒有細粒度的控制,只需啟動/停止就足夠了,這就足夠了。

此方案更接近移動應用程序中的自動更新功能。 基本上,如果在應用程序啟動/重新啟動時可用,則需要選擇新的程序集。

設計此方法的一種方法可能是建立一種通信機制,以便在啟動時向您的應用程序發出新程序集可用的信號(可能是version.txt文件)。 如果是,則相同的version.txt文件可以指向程序集的新位置。 是的 - 您可能最終創建了許多子文件夾以指向正確的版本,但這些可以由其他進程清理。

你可以使用像這樣的層次結構 -

版本\\ - 版本1.0 \\ - 版本2.0 \\

這種類型的設計更接近於眾所周知的自動更新范例。

您是否可以選擇不使用DirectoryCatalog並使用AssemblyCatalog加載目錄中的所有程序集? 您甚至可以轉到代碼plex並從DirectoryCatalog類中復制相同的代碼,該類讀取目錄並加載程序集。

您將失去動態加載它們的能力,但正如您所提到的那樣,這並非真正的要求。

暫無
暫無

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

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