TypedFactory 在组件将其用作依赖项之前处理
TypedFactory Disposes Before Component Using it As a Dependency
我有一个接口和一个类型化的工厂接口:
public interface ITransientItem : IDisposable
{
void DoWork(WorkItem item);
}
public interface ITransientItemFactory : IDisposable
{
ITransientItem Create();
void Destroy(ITransientItem item);
}
然后我实现了另一个接口IDependencyOwner : IDisposable
,它的实现者是:
public class DependencyOwner: IDependencyOwner
{
private ITransientItemFactory _factory;
public DependencyOwner(ITransientItemFactory factory)
{
_factory = factory;
}
public void PostWork(WorkItem workItem)
{
ITransientItem item = _factory.Create();
item.DoWork(workItem); //this is done on a seperate thread
_factory.Destroy(item);
}
public void Dispose()
{
//first wait for running items to dispose
//then do disposal stuff
}
}
DependencyOwner
是另一个对象的依赖项,可以有许多 DependencyOwner 的实现,这些实现由 CollectionResolver
子解析器解析。但我不认为它与这个问题有关。它的构造函数看起来像:
public TopLevel(IDependencyOwner[] dependencies)
容器注册如下所示:
WindsorContainer container = new WindsorContainer();
container.AddFacility(new TypedFactoryFacility());
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
container.Register(Component.For<TopLevel>());
container.Register(Component.For<IDependencyOwner>().ImplementedBy<DependencyOwner>();
//there will be more IDependencyOwner Implementations in the future
container.Register(Component.For<ITransientItem>().ImplementedBy<TransientItem>()
.LifeStyle.Transient);
container.Register(Component.For<ITransientItemFactory>().AsFactory());
TopLevel top = container.Resolve<TopLevel>();
代码实际上 运行 的一切都很好。是时候关闭程序了,问题来了。
ITransientItemFactory
在 DependencyOwner 的 Dispose 方法被调用之前就已经被释放了(我已经通过在 dispose 方法的第一行放置一个断点然后检查我的日志以查看错误来验证这一点已经存在)。这会导致任何正在处理的工作项失败,并且程序崩溃而不是正常结束。
我得到的异常是:
System.ObjectDisposedException: The factory was disposed and can no
longer be used. Object name: 'this'.
为什么温莎不尊重这种依赖性?
编辑:我在这里偶然发现了 this trick,并且能够确认工厂确实作为 DependencyOwner 的依赖项出现在依赖关系图中。
编辑 2:我刚刚自己实现了工厂并删除了类型工厂。这解决了我的问题(因为依赖性得到了尊重),但如果可以避免的话,我宁愿不这样做。仅供说明之用,本例中的注册变为:
WindsorContainer container = new WindsorContainer();
//container.AddFacility(new TypedFactoryFacility());
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
container.Register(Component.For<TopLevel>());
container.Register(Component.For<IDependencyOwner>().ImplementedBy<DependencyOwner>();
//there will be more IDependencyOwner Implementations in the future
//No reason to register it anymore, it will never be instantiated by the container
//container.Register(Component.For<ITransientItem>().ImplementedBy<TransientItem>()
//.LifeStyle.Transient);
//container.Register(Component.For<ITransientItemFactory>().AsFactory());
container.Register(Component.For<ITransientItemFactory>()
.ImplementedBy<FactoryImplementation>());
TopLevel top = container.Resolve<TopLevel>();
我为此贡献了一个修复程序,该修复程序已在 Castle.Windsor 4.1.0 中发布!
https://github.com/castleproject/Windsor/pull/344
https://github.com/castleproject/Windsor/releases/tag/v4.1.0
我有一个接口和一个类型化的工厂接口:
public interface ITransientItem : IDisposable
{
void DoWork(WorkItem item);
}
public interface ITransientItemFactory : IDisposable
{
ITransientItem Create();
void Destroy(ITransientItem item);
}
然后我实现了另一个接口IDependencyOwner : IDisposable
,它的实现者是:
public class DependencyOwner: IDependencyOwner
{
private ITransientItemFactory _factory;
public DependencyOwner(ITransientItemFactory factory)
{
_factory = factory;
}
public void PostWork(WorkItem workItem)
{
ITransientItem item = _factory.Create();
item.DoWork(workItem); //this is done on a seperate thread
_factory.Destroy(item);
}
public void Dispose()
{
//first wait for running items to dispose
//then do disposal stuff
}
}
DependencyOwner
是另一个对象的依赖项,可以有许多 DependencyOwner 的实现,这些实现由 CollectionResolver
子解析器解析。但我不认为它与这个问题有关。它的构造函数看起来像:
public TopLevel(IDependencyOwner[] dependencies)
容器注册如下所示:
WindsorContainer container = new WindsorContainer();
container.AddFacility(new TypedFactoryFacility());
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
container.Register(Component.For<TopLevel>());
container.Register(Component.For<IDependencyOwner>().ImplementedBy<DependencyOwner>();
//there will be more IDependencyOwner Implementations in the future
container.Register(Component.For<ITransientItem>().ImplementedBy<TransientItem>()
.LifeStyle.Transient);
container.Register(Component.For<ITransientItemFactory>().AsFactory());
TopLevel top = container.Resolve<TopLevel>();
代码实际上 运行 的一切都很好。是时候关闭程序了,问题来了。
ITransientItemFactory
在 DependencyOwner 的 Dispose 方法被调用之前就已经被释放了(我已经通过在 dispose 方法的第一行放置一个断点然后检查我的日志以查看错误来验证这一点已经存在)。这会导致任何正在处理的工作项失败,并且程序崩溃而不是正常结束。
我得到的异常是:
System.ObjectDisposedException: The factory was disposed and can no longer be used. Object name: 'this'.
为什么温莎不尊重这种依赖性?
编辑:我在这里偶然发现了 this trick,并且能够确认工厂确实作为 DependencyOwner 的依赖项出现在依赖关系图中。
编辑 2:我刚刚自己实现了工厂并删除了类型工厂。这解决了我的问题(因为依赖性得到了尊重),但如果可以避免的话,我宁愿不这样做。仅供说明之用,本例中的注册变为:
WindsorContainer container = new WindsorContainer();
//container.AddFacility(new TypedFactoryFacility());
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
container.Register(Component.For<TopLevel>());
container.Register(Component.For<IDependencyOwner>().ImplementedBy<DependencyOwner>();
//there will be more IDependencyOwner Implementations in the future
//No reason to register it anymore, it will never be instantiated by the container
//container.Register(Component.For<ITransientItem>().ImplementedBy<TransientItem>()
//.LifeStyle.Transient);
//container.Register(Component.For<ITransientItemFactory>().AsFactory());
container.Register(Component.For<ITransientItemFactory>()
.ImplementedBy<FactoryImplementation>());
TopLevel top = container.Resolve<TopLevel>();
我为此贡献了一个修复程序,该修复程序已在 Castle.Windsor 4.1.0 中发布!
https://github.com/castleproject/Windsor/pull/344
https://github.com/castleproject/Windsor/releases/tag/v4.1.0