2

C# 経由で .NET アセンブリを実行する際にいくつかの大きな問題が発生しています。静的クラスから静的メソッド (Main) を呼び出したい。現在のドメインで動作していましたが、そこからアセンブリをアンロードできないようです。

まず、新しい AppDomain を作成してみました。

AppDomain domain = AppDomain.CreateDomain("PluginDomain");

私の主な問題は、読み込もうとしているアセンブリの解決にあるため、AssemblyResolve イベントをフックしようとしました。

domain.AssemblyResolve += new ResolveEventHandler(this.OnAssemblyResolve);

ただし、これ(つまり、このクラス)のシリアル化に関するエラーが発生します。

以下を使用するだけで、たまたま BaseDirectory にあるアセンブリ ファイルを正常に読み込めました。

domain.Load("Assembly1");

しかし、問題のあるアセンブリは BaseDirectory の 2 つのサブディレクトリ内にあります。BaseDirectory\dir1\dir2\Assembly2.dll - 文字列アセンブリ名で domain.Load() を使用すると (PrivateBinPath を正しいサブディレクトリの場所に設定して)、またアセンブリ バイトで domain.Load() を使用すると、FileNotFoundException が発生します。 (File.ReadAllBytes() から)。

AppDomain.Load() が非推奨であることは承知していますが、静的メソッドを含むクラスを強制的に非静的かつインスタンス化可能にしたくないことを考えると、これが唯一の使用可能なメソッドのように思えました。

とにかく、アセンブリ ファイルが新しい AppDomain に正しく読み込まれるようにするにはどうすればよいですか?

これに関する私の主な目的は、自分のプログラムを呼び出すことができるアセンブリからメソッドを動的に実行することですが、必要に応じてアセンブリも完全にアンロードする必要があります。これは、プラグイン システムのようなものを意図しています。

4

1 に答える 1

5

Assembly.AssemblyResolve のイベント ハンドラーは、このアセンブリが読み込まれる同じ AppDomain にある必要があります。これは、このハンドラーが Assembly のインスタンスへの参照を返す必要があるためですが、アセンブリへの参照を取得するとすぐに自動的に読み込まれるため、アセンブリは両方の AppDomains に読み込まれます。

メイン アプリケーションと同じディレクトリに小さな別のアセンブリを作成することをお勧めします。このアセンブリには、MarshalByRefObject から派生したヘルパー クラスが 1 つだけ含まれ、アセンブリの解決/読み込みを処理でき、必要なプラグインの静的メソッドの呼び出しを提供できます。プラグインをロードする各 AppDomain にこのアセンブリをロードし、hepler クラスのインスタンスを作成して呼び出します。

public class HelperClass: MarshalByRefObject
{
    public void LoadPlugin(string PluginFileName)
    {
        //Load plugin assembly or register handler for Assembly.AssemblyResolve
        //AppDomain.CurrentDomain.Load()
        //AppDomain.CurrentDomain.AssemblyResolve += ...
        //Call plugin's static method
    }
}


AppDomain domain = AppDomain.CreateDomain("PluginDomain");
domain.Load("plugin_helper.dll");
HelperClass helper = (HelperClass)domain.CreateInstanceAndUnwrap("plugin_helper.dll", "HelperClass");
helper.LoadPlugin("plugin1.dll");
于 2012-04-21T02:51:25.300 に答える