私は Windsor 3.1.0 を使用しており、 Typed FactoryLifestyleTransient
を使用してコンポーネントをインスタンス化しています。参照ページで述べられているように、ファクトリから取得したすべてのオブジェクトを解放する必要があります。しかし、私はこのようなシナリオにいます
class MyTypedFactory
{
MyTransientCommand CreateCommand();
void Release(MyTransientCommand command);
}
class MyTransientCommand
{
public void Execute() { }
}
class ClassA
{
public ClassB CommandPopulator { get; set; }
public void Foo()
{
List<MyTransientCommand> commands = new List<MyTransientCommand>();
CommandsPopulator.Commands = commands;
for (int i=0; i<100; ++i)
{
CommandsPopulator.Bar();
}
foreach (MyTransientCommand command in commands)
{
command.Execute();
}
}
}
class ClassB
{
public MyTypedFactory Factory { get; set; }
List<MyTransientCommand> Commands { get; set; }
public void Bar()
{
Commands.Add(Factory.CreateCommand());
}
}
これは複雑すぎるように見えるかもしれませんが、コード内のオブジェクト フローを示しています。ここで、外部クラス ( )は、型指定されたファクトリによって作成されたコマンドをキューにClassB
取り込みます。commands
これらのオブジェクトが不要になったときに (Execute
ループの後) ファクトリで解放することは、全体的な問題になります。ループ内で解放できますが、解放メソッド自体の例外に対して安全ではありません。
class ClassA
{
public MyTypedFactory Factory { get; set; }
...
public void Foo()
{
...
foreach (MyTransientCommand command in commands)
{
command.Execute();
}
foreach (MyTransientCommand command in commands)
{
Factory.Release(command);
}
}
}
Release 呼び出しの 1 つがスローされた場合、残りのオブジェクトは解放されず、メモリ リークが発生します (これが発生してはならないことはわかっていますが、この種のものから防御しようとしています)。
MyTransientCommand
で作成した直後にリリースしても大丈夫ClassB.Bar
ですか?ClassA.Foo
コマンドオブジェクトのコレクションへの参照を保持しているため、メソッドが戻るまでGCによって解放されません。
WCF クライアント呼び出しを行い、WCF クライアントが Windsor でセットアップされている場合、リリースMyTransientCommand
しても問題ありませんか? またはより一般的には、Windsor が提供する他のコンポーネントを使用する場合は?ClassB.Bar
MyTransientCommand.Execute
MyTransientCommand.Execute
PS問題のコードは人工的で不自然に見えますが、そうです。これは、アルゴリズムに副作用が必要なためです。トランザクション内でデータベース内のデータの状態を変更すると、状況によっては WCF 呼び出しが発生する必要があります。これらの呼び出しは、トランザクション中ではなく、トランザクションが完了した後に行う必要があります。