11

Windsor Container に登録されている IDisposable を実装するオブジェクトがあり、それを破棄して、Dispose メソッドが呼び出され、次に Resolve が呼び出されたときに新しいインスタンスをフェッチするようにしたいと考えています。

する

container.Release(obj); 

Dispose() をすぐに自動的に呼び出しますか? それともする必要がありますか

obj.Dispose();
container.Release(obj);

リリースが正確に何をするかについてのドキュメントには何も見つかりませんでした

編集: 私が実行したテストの結果については、以下の回答を参照してください。問題は、シングルトン ライフサイクルを持つコンポーネントのインスタンスをコンテナに強制的にリリースさせるにはどうすればよいかということです。これは 1 か所で行うだけで済みますが、カスタム ライフサイクルを記述するのは非常に重いように思えます。それを行う組み込みの方法はありませんか?

4

3 に答える 3

14

これは、Windsor コンテナーを操作するときに人々が実際に気付いていないと思うことです。特に、使い捨ての一時的なコンポーネントが、自分で解放しない限り、破棄されるまでカーネルの存続期間中、コンテナーによって保持されるという驚くべき動作がよくありますが、それは文書化されています-ここを見てください-しかし、すぐに引用するには:

MicroKernel には、コンポーネントを破棄するためのルーティングを接続して実装できるプラグ可能なリリース ポリシーがあります。MicroKernel には、次の 3 つの IReleasePolicy 実装が付属しています。

  • AllComponentsReleasePolicy: すべてのコンポーネントを追跡して、MicroKernel インスタンスの破棄時に正しい破棄を強制します
  • LifecycledComponentsReleasePolicy: 廃棄ライフサイクルが関連付けられているコンポーネントのみを追跡します
  • NoTrackingReleasePolicy: 追跡を実行しません

インターフェイス IReleasePolicy を使用して、独自のリリース ポリシーを実装することもできます。

ポリシーをNoTrackingReleasePolicyに変更してから、自分で破棄を処理する方が簡単な場合があります。これも潜在的に危険ですが、ライフスタイルがほとんど一時的なものである場合 (または、コンテナーが破棄されたときにアプリケーションが閉じようとしている場合)それはおそらく大したことではありません。ただし、シングルトンが既に注入されているコンポーネントは参照を保持するため、シングルトンを「更新」しようとすると問題が発生する可能性があることに注意してください。これは悪い習慣のように思えます。アプリケーションを組み立てる方法を改善することで、まずこれを行います。

他のアプローチは、独自の廃止実装を使用してカスタム ライフサイクルを構築することです (したがって、シングルトンをリリースすると、一時的なライフサイクルと同じように、実際にはコンポーネントが破棄されます)。

別の方法として、サービスのデコレーターをシングルトン ライフスタイルでコンテナーに登録し、実際の基になるサービスを一時的なライフスタイルでコンテナーに登録する方法があります。コンポーネントを更新する必要がある場合は、保持されている一時的な基になるコンポーネントを破棄するだけです。デコレータによって解決され、新しく解決されたインスタンスに置き換えられます (デコレータを取得しないように、サービスではなくコンポーネント キーを使用して解決します) - これにより、他のシングルトン サービス (「更新」されていない) の問題が保持されなくなります。古いサービスは破棄されて使用できなくなりますが、機能させるには少しキャストなどが必要です。

于 2008-10-03T11:55:47.120 に答える
3

コンテナに追加したときに指定したコンポーネントのライフスタイルによって異なります。

ライフスタイルがプールされている場合は、Release() を使用します。これにより、次の取得のためにコンポーネントがプールに戻されます (オブジェクトは破棄されないため、破棄は不適切です)。

ライフスタイルが一時的なものである場合、コンポーネントを取得すると新しいオブジェクトが作成されます。この場合、処分はあなた次第であり、Release を呼び出す必要はありません。

ライフスタイルが Thread の場合、同じコンポーネントが各スレッドに使用され、破棄されません。

ライフスタイルがシングルトンの場合、コンポーネントは 1 つだけ作成され、破棄されません。

ほとんどの場合、一時的なコンポーネントを使用していますか? (タイムリーにそれらを破棄することが懸念される場合)その場合は、それを using でラップするだけで設定が完了します(または、自分で dispose をどこかで呼び出します)。

using(ISomeService service = container.Resolve<ISomeService>())
{
 // Do stuff here
 // service.Dispose is automatically called 
}

編集- はい、シングルトンを「リフレッシュ」または破棄して再作成するには、コンテナを破棄するか、カスタム ライフサイクルを記述する必要があります。カスタム ライフサイクルを実行することは、実際にはそれほど難しくなく、そのためのロジックを 1 か所にまとめています。

于 2008-09-17T17:15:08.683 に答える
1

さて、私はテストを実行してきましたが、ライフスタイルが一時的である場合にのみContainer.Release()IDisposableのDispose()メソッドを暗黙的に実行させるようです(これはおそらく正確ではありませんが、ライフスタイルがシングルトンの場合は気の毒なことをしないということです) )。

これを呼び出すContainer.Dispose()と、破棄可能なメソッドも呼び出されますが、残念ながら、カーネル全体が破棄され、すべてのコンポーネントを再度追加する必要があります。

var container = new WindsorContainer();
container.AddComponentWithLifestyle<MyDisposable>(Castle.Core.LifestyleType.Singleton);
var obj = container.Resolve<MyDisposable>();  // Create a new instance of MyDisposable
obj.DoSomething();
var obj2 = container.Resolve<MyDisposable>();  // Returns the same instance as obj
obj2.DoSomething();
container.Dispose();  // Will call the Disposable method of obj
// Now the components need to be added back in   
 container.AddComponentWithLifestyle<MyDisposable>(Castle.Core.LifestyleType.Singleton);
var obj3 = container.Resolve<MyDisposable>();  // Create a new instance of MyDisposable

幸いなことに、私の場合は、すべてのコンポーネントを削除するだけの余裕があり、それらをかなり簡単に復元できます。ただし、これは最適ではありません。

于 2008-09-17T17:51:40.890 に答える