1

アセンブリをホット スワップ (更新) しようとしています。通常のワークフローでは、いくつかの変更を行い、アセンブリをビルドし、いくつかの変更を行ってから再度ビルドします。理想的な世界では、ホスト アプリは新しいバージョンのアセンブリを取得します (更新されたタイプ)。

小さなプラグイン ローダー クラスは次のとおりです。

public class PluginLoader<T>
{
    private CompositionContainer _compositionContainer;
    private RegistrationBuilder _registrationBuilder;
    private DirectoryCatalog _catalog;

    [ImportMany(AllowRecomposition = true)]
    public IList<T> Plugins { get; set; }

    public PluginLoader(string pluginsDirectory)
    {
        Plugins = new List<T>();
        SetShadowCopy();

        _registrationBuilder = new RegistrationBuilder();
        _registrationBuilder
           .ForTypesDerivedFrom(typeof(T))
           .SetCreationPolicy(CreationPolicy.NonShared)
           .Export<T>();

        _catalog = new DirectoryCatalog(pluginsDirectory, _registrationBuilder);

        _compositionContainer = new CompositionContainer(_catalog, CompositionOptions.DisableSilentRejection);
        _compositionContainer.ComposeParts(this);
    }

    public void Reload()
    {
        _catalog.Refresh();
        _compositionContainer.ComposeParts(this);
    }

    private static void SetShadowCopy()
    {
        AppDomain.CurrentDomain.SetShadowCopyFiles();
        AppDomain.CurrentDomain.SetCachePath(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "ShadowCopyCache"));
        AppDomain.CurrentDomain.SetShadowCopyPath(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Plugins"));
    }
}

FileSystemWatcher を使用して新しいプラグインが plugins フォルダーにドロップされたことを認識するコードがあり、それが発生したときに Reload を呼び出しますが、アセンブリの新しいバージョンは実際には読み込まれません。ポインタはありますか?

ノート:

  • 新しいアセンブリまたは削除された型は認識されません。新しいアセンブリがまったく認識されないかのようです。
  • 確認しましたが、構成やその他のエラーもありません。少し迷っています:D
  • 認識されない同じアセンブリを別のコンパイラ (Roslyn) でビルドすると、それが認識されることに注意することが重要です (これは、アセンブリが何らかの形で異なる必要があることだけを示しています)。
4

1 に答える 1

1

で呼び出されたメソッドSetShadowCopyは非推奨です。既存の で ShadowCopy を有効にすることはできませんAppDomain。新しい AppDomain で ShadowCopy を有効にする方法の例については、この回答をご覧ください。

DirectoryCatalog.Refreshは、既に読み込まれているアセンブリを更新します。ファイルの削除と追加のみをチェックします。大雑把な回避策については、この回答をご覧ください。私は単純なシナリオしかテストしていないので、そのようなアプローチがスレッドセーフか本番対応かはわかりません。もう 1 つの方法は、更新も処理できる独自の DirectoryCatalog を作成することです。MEF ソース コードが利用可能です (残りのフレームワークと同様)。注意が必要なのは、DirectoryCatalog の実装がロックに Microsoft の内部クラスを使用しているため、スレッド セーフです。

于 2014-02-06T12:54:15.893 に答える