web-dev-qa-db-ja.com

プライマリAppDomainからアセンブリをアンロードする方法は?

メインのAppDomainに読み込まれているアセンブリをアンロードする方法を教えてください。

私は次のコードを持っています:

var Assembly = Assembly.LoadFrom( FilePathHere );

完了したら、このアセンブリをアンロードできるようにする必要があります。

ご協力いただきありがとうございます。

42
Derik Whittaker

。netバージョンコア3.0以降の場合:

これでアセンブリをアンロードできます。 appdomainsは.netコアでは使用できなくなっていることに注意してください。代わりに、1つ以上のAssemblyLoadContextを作成し、そのコンテキストを介してアセンブリをロードしてから、そのコンテキストをアンロードできます。 AssemblyLoadContext 、または プラグインのロードとアンロードをシミュレートするこのチュートリアル を参照してください。

。netコア3より前の.netバージョンの場合、netframework 4以下を含む

Appdomainからアセンブリをアンロードすることはできません。 appdomainsを破棄できますが、アセンブリがappdomainに読み込まれると、appdomainの存続期間中は存在します。

Jason Zanderの説明 Assembly.Unloadメソッドがないのはなぜですか?

3.5を使用している場合は、アドインフレームワークを使用して、さまざまなAppDomain([canアンロード、すべてのアセンブリのアンロード))の管理/呼び出しを簡単にすることができます。それより前のバージョンを使用している場合は、新しいappdomainを自分で作成してアンロードする必要があります。

35
Philip Rieck

また、これは非常に古いことを知っていますが、この問題が発生している人を助けるかもしれません!ここに私がそれをするために見つけた一つの方法があります!代わりに:

var Assembly = Assembly.LoadFrom( FilePathHere );

これを使って:

var Assembly = Assembly.Load( File.ReadAllBytes(FilePathHere));

これは実際には、ファイル自体ではなく、アセンブリファイルの「コンテンツ」をロードします。つまり、アセンブリファイルにファイルロックが設定されていません。したがって、アプリケーションを閉じたり、別のAppDomainやマーシャリングを使用したりせずに、コピー、削除、またはアップグレードできます。

PROS: 1ライナーのコードで修正するのは非常に簡単です! CONS: AppDomain、Assembly.Location、またはAssembly.CodeBaseは使用できません。

次に、アセンブリで作成されたインスタンスを破棄するだけです。例えば:

Assembly = null;
23
Kirk Herron

AppDomain全体をアンロードしないと、アセンブリをアンロードできません。 理由はここにあります

  1. そのコードをアプリドメインで実行しています。つまり、機能し続けることを期待しているアドレスが含まれている可能性のある呼び出しサイトと呼び出しスタックがある可能性があります。

  2. アセンブリによって既に実行中のコードへのすべてのハンドルと参照を追跡できたとしましょう。コードを生成しなかったとすると、アセンブリの解放に成功すると、メタデータとILのみが解放されます。 JITされたコードは引き続きアプリドメインローダーヒープに割り当てられます(JITされたメソッドは、呼び出された順にバッファーに順次割り当てられます)。

  3. 最後の問題は、ロードされて共有されたコードに関連しています。それ以外の場合は、正式には「ドメインニュートラル」と呼ばれます(ngenツールで/ sharedを確認してください)。このモードでは、アセンブリのコードが生成され、任意のアプリドメインから実行されます(ハードワイヤードではありません)。

アンロードが完全にサポートされているアプリケーションドメイン境界の周囲にアプリケーションを自然に設計することをお勧めします。

15
Mark Cidade

一時アセンブリを別のAppDomainにロードする必要があります。使用していないときは、そのAppDomainをアンロードできます。安全で高速です。

10
Nipun

後でアンロードできる一時的なコードが必要な場合は、必要に応じて、DynamicMethodクラスが必要な機能を実行する場合があります。しかし、それはあなたにクラスを与えません。

4
Khoth

私はその古いことを知っていますが、誰かを助けるかもしれません。ストリームからファイルをロードして解放できます。それは私のために働いた。私は解決策を見つけました [〜#〜]ここ[〜#〜]

それが役に立てば幸い。

実行時にdllをコンパイルして実行し、すべてのリソースをアンロードする方法の良い例を次に示します。 http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm

1
GenZiy

別の方法として、アセンブリが最初にロードされたばかりの場合、publicKeyなどのアセンブリの情報を確認するには、それをロードせず、最初にAssemblyNameのみをロードして情報を確認する方が良いでしょう。

AssemblyName an = AssemblyName.GetAssemblyName ("myfile.exe");
byte[] publicKey = an.GetPublicKey();
CultureInfo culture = an.CultureInfo;
Version version = an.Version;

[〜#〜]編集[〜#〜]

アプリドメインにアセンブリを取得せずに、アセンブリに型を反映する必要がある場合は、Assembly.ReflectionOnlyLoadFromメソッドを使用できます。これにより、アセンブリ内の型を確認できますが、インスタンス化できず、AppDomainにアセンブリをロードできません。

この例を説明として見てください

public void AssemblyLoadTest(string assemblyToLoad)
{
    var initialAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //4

    Assembly.ReflectionOnlyLoad(assemblyToLoad);
    var reflectionOnlyAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //4

    //Shows that Assembly is NOT loaded in to AppDomain with Assembly.ReflectionOnlyLoad
    Assert.AreEqual(initialAppDomainAssemblyCount, reflectionOnlyAppDomainAssemblyCount); // 4 == 4

    Assembly.Load(assemblyToLoad);
    var loadAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //5

    //Shows that Assembly is loaded in to AppDomain with Assembly.Load
    Assert.AreNotEqual(initialAppDomainAssemblyCount, loadAppDomainAssemblyCount); // 4 != 5
}
0