12

実行時にアセンブリを上書きできるように、アプリケーションが 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 コンポーネント カタログにアクセスします。ただし、コンポジション コンテナーはシャドウコピー ドメイン内でのみ初期化されるようです (これは理にかなっています)。これは、アプリケーション ドメインでは null であることを意味します。これを行うためのより良い方法があるかどうか、またはクロスドメインクエリを使用して MEF コンポーネントを取得する方法があるかどうか疑問に思っていました

4

3 に答える 3

3

Dan Bryant と zync の解決策に従いたくない場合は、単純に新しい .xml ファイルでアプリケーションを実行するシェル アプリケーションを作成できますAppDomain

アプローチは次のとおりです。

  1. シェル アプリケーションとなる新しいアプリケーション プロジェクトを作成します。
  2. シェル アプリケーションで を作成しAppDomain、シャドウ コピーを有効にし、必要に応じてシャドウ コピーを有効にするディレクトリを指定します。
  3. AppDomain.ExecuteAssembly現在のアプリケーションを呼び出すために使用します。

アプリケーションの代わりにクラス ライブラリがある場合は、次のことを試すことができます。

  1. 新しいクラス ライブラリ プロジェクトを作成します。
  2. 次のインターフェイスを新しいクラス ライブラリ プロジェクトに追加します。

    public interface IRemoteLoader  
    {  
        void Load();  
        void Unload();  
    }
    
  3. 新しい AppDomain で実行する必要があるクラス ライブラリに、このインターフェイスの実装を追加します。Loadメソッドとメソッドに、Unloadそれぞれ初期化とクリーンアップを実行するコードを追加する必要があります。クラスを から派生させMarshalByRefObjectます。これは、.NET Remoting が両方の AppDomains でプロキシ オブジェクトを作成するために必要です。

  4. 新しい AppDomain を作成したら、 を使用CreateInstanceAndUnwrapして、手順 3 のローダー クラスのインスタンスを作成します。

  5. 手順 4 で作成したオブジェクトでLoadとを使用します。Unload

きめ細かな制御を行わず、単に開始/停止するだけで十分な場合は、これで十分です。

于 2012-10-04T14:19:32.213 に答える
-1

このシナリオは、モバイル アプリの自動更新機能に近いものです。基本的に、アプリの開始/再起動時に利用可能な場合は、新しいアセンブリを取得する必要があります。

これを設計する 1 つの方法は、開始時に新しいアセンブリ (おそらく version.txt ファイル) が利用可能であることをアプリに通知する通信メカニズムを用意することです。はいの場合、同じ version.txt ファイルがアセンブリの新しい場所を指している可能性があります。はい - 正しいバージョンを指すように多数のサブフォルダーを作成することになるかもしれませんが、これらは別のプロセスによってクリーンアップされる可能性があります。

次のような階層構造を使用できます-

バージョン\ - バージョン1.0\ - バージョン2.0\

このタイプの設計は、よく知られている自動更新のパラダイムに近いものになります。

于 2012-10-01T14:11:44.303 に答える