我有一个实现IDisposable的对象,该对象已在Windsor容器中注册,我想对其进行处理,因此将调用Dispose方法,并在下次调用Resolve时获取一个新实例。
是否
立即自动调用Dispose()吗? 还是我需要做
1 2
| obj.Dispose();
container.Release(obj); |
在文档中找不到有关Release确切功能的任何信息
编辑:
有关我运行的测试结果,请参见下面的答案。 现在的问题是,如何强制容器释放具有单例生命周期的组件实例? 这只需要在一个地方完成,编写自定义生命周期似乎太繁重了,难道没有内置的方法吗?
我认为这是人们在使用Windsor容器时并没有真正意识到的事情-尤其是经常令人惊讶的行为,即在容器的整个生命周期中,一次性瞬态组件在容器中一直保持着直到被处置,除非您自己释放它们-尽管它已被记录-在这里看看-但快速引用:
the MicroKernel has a pluggable release policy that can hook up and implement some
routing to dispose the components. The MicroKernel comes with three IReleasePolicy implementations:
-
AllComponentsReleasePolicy: track all components to enforce correct disposal upon the MicroKernel instance disposal
-
LifecycledComponentsReleasePolicy: only track components that have a decommission lifecycle associated
-
NoTrackingReleasePolicy: does not perform any tracking
You can also implement your own release policy by using the interface IReleasePolicy.
您可能会发现更容易的是将策略更改为NoTrackingReleasePolicy,然后自行处理-这同样有潜在的风险,但是如果您的生活方式是暂时的(或者如果处置容器时,您的应用程序将要关闭,则无论如何)这可能没什么大不了的。但是请记住,任何已经注入单例的组件都将保留一个引用,因此您最终可能会导致尝试"刷新"单例时出现问题-这似乎是一种不好的做法,我想知道您是否可以避免必须首先,通过改善应用程序的组合方式来做到这一点。
其他方法是使用其自己的停用实现来构建自定义生命周期(因此释放单例实际上将处置组件,就像瞬态生命周期一样)。
另一种方法是在容器中注册具有单一生活方式的服务装饰器,但在容器中注册具有过渡生活方式的实际基础服务-然后,当您需要刷新组件时,只需处置持有的过渡基础组件即可由装饰器替换为新解析的实例(使用components键而不是服务来解析它,以避免获取装饰器)-这样可以避免其他单例服务(未"刷新")的问题到已经过时的服务上,这些服务已经过时了,无法使用,但是需要大量的转换等才能使其正常工作。
这取决于您将其添加到容器中时指定的组件的寿命。
如果生活方式是集中的,则可以使用Release()。这会将组件放回池中,以进行下一次检索(对象不会被销毁,因此处理会很糟糕)
如果生活方式是短暂的,则在获取组件时会创建一个新对象。在这种情况下,处置取决于您,您无需致电Release
如果生活方式是Thread,则每个线程都使用相同的组件,而不销毁。
如果生活方式为Singleton,则只会创建一个组件,并且不会破坏它。
您很可能正在使用瞬态组件? (如果您担心要及时处理它们)
在这种情况下,只需将其包装成一个using就可以了(或在某个地方自己叫处理)
1 2 3 4 5
| using(ISomeService service = container.Resolve<ISomeService>())
{
// Do stuff here
// service.Dispose is automatically called
} |
编辑-是的,为了"刷新"或处理并重新创建您的单例,您需要销毁容器或编写自定义生命周期。进行自定义生命周期实际上并不那么困难,并且将这样做的逻辑保持在一个地方。
好吧,所以我一直在运行测试,并且似乎Container.Release()只会隐式地导致IDisposable的Dispose()方法仅在生活方式为瞬态时执行(这可能不完全正确,但要点是,它不会做大胆的事情) (如果生活方式是单身人士)。
现在,如果您调用Container.Dispose(),它将也调用一次性方法,尽管不幸的是它将处置整个内核,并且您必须将所有组件添加回去:
1 2 3 4 5 6 7 8 9 10
| 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 |
幸运的是,我有能力删除所有组件,并且可以相当轻松地还原它们。但是,这不是最佳的。