5

問題文: 関連付けられたアセンブリを上書きできるようにするプラグイン システムを実装します (ファイルのロックを回避します)。.Net では、特定のアセンブリをアンロードできず、AppDomain 全体のみをアンロードできます。

問題を解決しようとしたときに、すべてのソリューションが複数の AppDomains の使用を参照したため、これを投稿しています。複数の AppDomains を正しく実装することは、プロジェクトの開始時に設計された場合でも非常に困難です。

また、Speech Server ワークフローの InvokeWorkflow アクティビティの設定としてドメイン間で Type を転送する必要があったため、AppDomains は機能しませんでした。残念ながら、ドメイン間で型を送信すると、アセンブリがローカルの AppDomain に挿入されます。

また、これは IIS に関連しています。IIS には、メモリにロードされている間に実行中のアセンブリを上書きできるシャドウ コピー設定があります。問題は、(少なくとも XP では、2003 年の実稼働サーバーでテストしなかった) アセンブリをプログラムでロードすると、シャドウ コピーが機能しないことです (IIS ではなく DLL をロードしているため)。

4

3 に答える 3

8
  1. アセンブリが既に読み込まれているかどうかを確認します (同じアセンブリを何度も読み込むことによるメモリ リークを避けるため)。
  2. 読み込まれていない場合は、アセンブリをバイト配列に読み取ります。これにより、ファイルのロックが防止されます。
  3. Assembly.Load への引数としてバイト配列を指定します。

次のコードは、アセンブリの FullName を知っていることを前提としています。

Assembly assembly = null;

foreach(Assembly loadedAssembly in AppDomain.CurrentDomain.GetAssemblies())
    if (loadedAssembly.FullName == "foobar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
        assembly = loadedAssembly;

if(assembly == null)
{
    byte[] studybin = System.IO.File.ReadAllBytes(@"C:\pathToAssembly\foobar.dll");
    assembly = Assembly.Load(studybin);                
}

ディレクトリ内の特定のアセンブリを見つけようとしている場合は、'System.Reflection.AssemblyName.GetAssemblyName(path);' を実行できることに注意してください。FullName が探しているものと一致するかどうかを確認します。'GetAssemblyName(path)' は、アセンブリを現在の AppDomain に挿入しません。

また、このソリューションは、ほとんど再起動する必要がなく、アセンブリが頻繁に変更されるアプリケーションには適していないことに注意してください。アセンブリが読み込まれるたびに、アプリケーションのメモリ フットプリントが増加します。アセンブリをアンロードする方法はないため、メモリ使用量を削減する唯一のオプションは、アプリケーションを再起動することです。ただし、この制限は、多くの場合、複数のアプリ ドメインを使用することによる大きなパフォーマンス、メモリ、およびコードの複雑さのオーバーヘッドよりも望ましいものです。sを使用する場合も、この制限は避けられませんType

于 2009-01-19T18:54:12.777 に答える
2

プラグイン アーキテクチャを使用してシステムを構築するための本格的な方法に関心がある場合は、現在 .NET Framework の一部である MAF (Managed Add-in Framework)、つまり System.AddIn 名前空間を調べてみてください。

アドインの分離とバージョン管理、さらにはコントラクトとの下位互換性を管理するのに役立ちます。

ただし、ここには少し学習曲線があるため、これはまさにあなたが探しているものではないかもしれません.

http://msdn.microsoft.com/en-us/library/bb384200.aspx

于 2009-07-20T15:53:23.020 に答える
2

アドインを分離したい場合は、...

  1. アドインと対話する MarshallByRefObject を拡張する型を作成します (FOOMASTER と呼びましょう)。
  2. 新しいアプリドメインを作成します (addinLand と呼びましょう)
  3. addinLand.CreateInstanceAndUnwrap を呼び出して、addinLand で FOOMASTER のインスタンスを作成し、現在のアプリ ドメインでプロキシを取得します。
  4. FOOMASTER にアドインをロードするように指示する

これで、アドインが addinLand に読み込まれ、FOOMASTER プロキシを介してプライマリ アプリケーション ドメインからアドインとやり取りできるようになりました。アドインがクラッシュしても、アプリケーションはダウンしません。

これは興味深い、やや紛らわしいプロセスです。私は当初、アドインをロードし、透過的なプロキシとして現在のアプリ ドメインに持ち込むというアイデアを考えていましたが、最良の設計は、アドインを、作成したより複雑な型 (FOOMASTER) と相互作用する単純なオブジェクトとして残し、拡張することです。 addinLand アプリ ドメインに読み込まれ、対話する透過プロキシを持つ MarshallByRefObject。

CLR Via C# の第 21 章と第 22 章は、プロセスを理解するのに非常に役立ちます。

于 2009-07-20T15:39:08.790 に答える