C# Castle Windsor使用类型化工厂创建组件后是否可以发布组件
我正在使用Windsor 3.1.0,并使用C# Castle Windsor使用类型化工厂创建组件后是否可以发布组件,c#,castle-windsor,C#,Castle Windsor,我正在使用Windsor 3.1.0,并使用LifestyleTransient实例化一个组件。正如在参考页面中所说,我必须释放我从工厂得到的每一件物品。然而,我在这样的场景中 class MyTypedFactory { MyTransientCommand CreateCommand(); void Release(MyTransientCommand command); } class MyTransientCommand { public void Execut
LifestyleTransient
实例化一个组件。正如在参考页面中所说,我必须释放我从工厂得到的每一件物品。然而,我在这样的场景中
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.Bar
中创建了MyTransientCommand
后立即释放该命令可以吗?在ClassA.Foo
方法返回之前,GC不会释放它,因为它持有对commands对象集合的引用
如果MyTransientCommand.Execute
进行WCF客户端调用并且WCF客户端已与Windsor一起设置,则在ClassB.Bar
中释放MyTransientCommand
是否可以?或者更一般地说,如果MyTransientCommand.Execute使用Windsor提供的其他组件
p.S.问题中的代码看起来是人为的、不自然的,事实确实如此。这是因为算法必须有副作用:在某些情况下,在事务中更改数据库中数据的状态必须引发WCF调用。这些调用必须在事务完成后而不是在事务期间进行。通常,我会依赖于创建/注入对象的类来负责释放它,但以您描述的方式释放它不应该导致任何问题-您可以将释放代码放在一个
中
foreach (var command in commands)
{
try
{
command.Execute();
}
finally
{
Factory.Release(command);
}
}
为了扩展一点,Castle将注入所有必要的依赖项(只要您的工厂设置正确)。从容器中释放对象就是释放该实例。如果在Execute()
方法中修改注入的LifestyleSingleton
对象,可能会遇到并发问题,但这与将其从容器中释放无关。否,在使用组件之前释放组件是不合适的。Windsor跟踪嵌套组件的生存期,因此释放根组件通常会释放其子组件。我希望避免使用具有潜在无效状态的组件
因此,我最终采用了以下方式发布命令
class ClassA
{
public MyTypedFactory Factory { get; set; }
public ClassB CommandPopulator { get; set; }
public void Foo()
{
List<MyTransientCommand> commands = new List<MyTransientCommand>();
try
{
CommandsPopulator.Commands = commands;
for (int i=0; i<100; ++i)
{
CommandsPopulator.Bar();
}
foreach (MyTransientCommand command in commands)
{
command.Execute();
}
}
finally
{
foreach (MyTransientCommand command in commands)
{
try
{
Factory.Release(command);
}
catch (Exception exception)
{
Log(exception);
}
}
}
}
}
A类
{
公共MyTypedFactory工厂{get;set;}
公共类B命令填充器{get;set;}
公共图书馆
{
List命令=new List();
尝试
{
CommandsOperator.Commands=命令;
对于(inti=0;使用try/finally块是个好主意。但是如果CommandsPopulator.Bar()中的一些
调用失败?队列中已经存在的对象将永远不会被释放。我认为必须包装在try
中的是ClassA.Foo
的方法体,在命令
声明之后一直到最后。然后需要第三个释放循环,如我在问题中所示。这个释放循环仍然放在中e> 最后
对于异常是不安全的:如果其中一个Release
调用抛出,循环将退出,其余的命令将不会被释放。
class ClassA
{
public MyTypedFactory Factory { get; set; }
public ClassB CommandPopulator { get; set; }
public void Foo()
{
List<MyTransientCommand> commands = new List<MyTransientCommand>();
try
{
CommandsPopulator.Commands = commands;
for (int i=0; i<100; ++i)
{
CommandsPopulator.Bar();
}
foreach (MyTransientCommand command in commands)
{
command.Execute();
}
}
finally
{
foreach (MyTransientCommand command in commands)
{
try
{
Factory.Release(command);
}
catch (Exception exception)
{
Log(exception);
}
}
}
}
}