AppDomainとAssemblyの動的なロードとアンロード
この問題をわかりやすく説明するために、例を見てみましょう。この例では、WinForm 上にボタンがあり、ユーザーがそれをクリックすると、既存のアセンブリがロードされ、アセンブリの FullName がインターフェイス内の Label コントロールに表示されます。以下のコードのように、Assembly.LoadFile メソッドを実行し、FullName プロパティを使用して表示します。
- private void button1_Click(object sender, EventArgs e)
- {
- Assembly assembly = Assembly.LoadFile(@"C:\testlib.dll");
- label1.Text = assembly.FullName;
- }
もちろん、プログラムは正常に実行され、コンパイル時や実行時のエラーは見当たりません。しかし、このプログラムを終了せずに、testlib.dllという名前のコンパイルに戻ると、Visual Studioはコンパイルを完了できないことがわかります。これは、このファイルが他のプロセスで使用されていることを示唆しています。
実は、今回のプログラムはこのtestlib.dllとはあまり関係がなく、testlib.dllの基本情報を表示するだけのプログラムです。もしtestlib.dllが共有ライブラリであれば、リソースの排他性の問題は他のプログラムにも影響します。
AssemblyにはUnloadの機能がありませんが、AppDomainを使うことでこの問題を解決することができます。基本的な考え方は、新しいAppDomainを作成し、新しいAppDomainにアセンブリをロードし、その中のメソッドを呼び出し、その結果を返すというものです。注意:ロードしたアセンブリを、現在のアプリケーションドメイン(AppDomain)に直接返すことはできません。
まず、新しい AppDomain にアセンブリをロードする RemoteLoader を作成し、アセンブリの FullName が利用できるように、プロパティを外部にアドバタイズします。そのコードは以下の通りです。
- public class RemoteLoader : MarshalByRefObject
- {
- private Assembly アセンブリ。
- public void LoadAssembly(string fullName)
- {
- assembly = Assembly.LoadFrom(fullName)。
- }
- public string FullName
- {
- get { return assembly.FullName; }.
- }
- }
次に、LocalLoaderを作成します。この機能は、新しいAppDomainを作成し、この新しいAppDomainでRemoteLoaderを呼び出し、RemoteLoaderを通してアセンブリを作成し、アセンブリの情報を取得することです。このとき、呼び出されたアセンブリは当然、新しいAppDomainにロードされる。最後に、LocalLoaderもAppDomainをアンロードするための新しいメソッドを提供する必要があります。そのコードは以下の通りです。
- public class LocalLoader
- {
- private AppDomain appDomain;
- private RemoteLoader remoteLoader;
- public LocalLoader()
- {
- AppDomainSetup setup = new AppDomainSetup()。
- setup.ApplicationName = "Test"。
- setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
- setup.PrivateBinPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "private") とします。
- setup.CachePath = setup.ApplicationBase.CachePath。
- setup.ShadowCopyFiles = "true";
- setup.ShadowCopyDirectories = setup.ApplicationBase.Setup.ShadowCopyDirectories。
- appDomain = AppDomain.CreateDomain("TestDomain", null, setup);
- 文字列名 = Assembly.GetExecutingAssembly().GetName().FullName.FullName.FullName.FullName;
- remoteLoader = (RemoteLoader)appDomain.CreateInstanceAndUnwrap()
- という名前を付けます。
- typeof(RemoteLoader).FullName)を使用します。
- }
- public void LoadAssembly(string fullName)
- {
- remoteLoader.LoadAssembly(fullName)を実行します。
- }
- public void Unload()
- {
- AppDomain.Unload(appDomain)を実行します。
- appDomain = nullとする。
- }
- public string FullName
- {
- 得る
- {
- remoteLoader.FullNameを返します。
- }
- }
- }
最後に、WinFormのButton Clickイベントハンドラを以下のような形に変更します。
- private void button1_Click(object sender, EventArgs e)
- {
- LocalLoader ll = new LocalLoader()。
- ll.LoadAssembly(@"C:\testlib.dll") を実行します。
- label1.Text = ll.FullName;
- ll.Unload()を実行します。
- }
上記の変更を行った後、当プログラムはアセンブリのFullNameも正しく表示し、アセンブリ情報を表示した後、testlib.dllのリソース排他性が他のプログラムに影響しないよう、新しく作成したAppDomainを積極的にアンロードしています。
参考 http://www.microsoft.com/china/msdn/library/langtool/vcsharp/csharp05162002.mspx?mfr=true
関連
-
C# string.format でのエラー: 入力文字列が正しい形式でない
-
C# indexof() の使用法
-
C#の遅延関数の使用
-
C#高精度遅延コード実行時間(us/ns)
-
C#の面接質問100選(.net開発者必見)
-
C#とC++の型対応表まとめ
-
このリソースにアクセスするには完全な認証が必要です Unauthorized
-
C#のビルドコードで、すべてのコードパスが値を返さないエラーが発生する
-
エラーです。名前 'Encoding' は現在のコンテキストに存在しない ソリューション
-
C# データベース操作エラー。この接続に関連付けられた開いているDataReaderがすでにあり、これを閉じる必要があります...
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
c# - デシリアライズ・エラー。入力文字列が正しい形式でない
-
C#でUSBデバイスを操作する方法
-
エラーです。コレクションが変更されました。列挙操作が実行されない可能性があります。
-
Unityがエラーを報告します。コレクションが変更されました。列挙操作が実行されない可能性があります。
-
VS エラー LNK2005:**already defined in **.obj
-
HTTP エラー 500.22 - 内部サーバー エラー-IIS7 Asp.net2.0 ウェブサイトの実行ソリューションに失敗しました。
-
インデックスが配列の範囲外であった。
-
System.InvalidOperationException: ConnectionString プロパティが初期化されていません。
-
ASP.NET URL変更によるページ受け渡し
-
GDI+でジェネリックエラーが発生しました@System.Drawing.Image.RotateFlip