11

我有一个实现 IDisposable 的对象,该对象在 Windsor Container 中注册,我想处理它,因此调用它的 Dispose 方法,下次调用 Resolve 时它会获取一个新实例。

container.Release(obj); 

立即自动调用 Dispose()?还是我需要做

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

在文档中找不到任何关于 Release 究竟是做什么的

编辑: 有关我运行的测试结果,请参阅下面的答案。现在问题变成了,如何强制容器释放具有单例生命周期的组件实例?这只需要在一个地方完成,编写自定义生命周期似乎太重了,没有内置的方法吗?

4

3 回答 3

14

这是我认为人们在使用 Windsor 容器时并没有真正意识到这一点——尤其是在内核的生命周期内,容器会一直持有一次性瞬态组件直到它被丢弃,除非你自己释放它们——尽管如此它被记录在案 - 看看这里- 但要快速引用:

MicroKernel 有一个可插拔的发布策略,可以连接并实现一些路由来处理组件。MicroKernel 带有三个 IReleasePolicy 实现:

  • AllComponentsReleasePolicy:跟踪所有组件以在 MicroKernel 实例处置时强制正确处置
  • LifecycledComponentsReleasePolicy:仅跟踪关联了退役生命周期的组件
  • NoTrackingReleasePolicy:不执行任何跟踪

您还可以使用接口 IReleasePolicy 实现您自己的发布策略。

您可能会发现更容易将策略更改为NoTrackingReleasePolicy,然后自己处理处置 - 这也有潜在风险,但如果您的生活方式在很大程度上是短暂的(或者当您的容器被处置时,您的应用程序无论如何都将关闭)这可能没什么大不了的。但是请记住,任何已经注入单例的组件都将持有一个引用,因此您最终可能会在尝试“刷新”您的单例时导致问题 - 这似乎是一种不好的做法,我想知道您是否可以避免不得不首先通过改进应用程序的组合方式来做到这一点。

其他方法是使用自己的退役实现来构建自定义生命周期(因此释放单例实际上会处置组件,就像瞬态生命周期一样)。

或者,另一种方法是使用单例生活方式在容器中注册您的服务的装饰器,但您在容器中注册的实际底层服务具有瞬态生活方式 - 然后当您需要刷新组件时,只需处置持有的瞬态底层组件由装饰器替换它并用一个新解决的实例替换它(使用 components 键而不是服务来解决它,以避免获取装饰器) - 这避免了与其他单例服务(未被“刷新”)持有的问题到过时的服务上,这些服务已经被处理使它们无法使用,但确实需要一些强制转换等才能使其工作。

于 2008-10-03T11:55:47.120 回答
3

这取决于您在将组件添加到容器时指定的组件的生活方式。

如果生活方式是池化的,您将使用 Release()。这会将组件放回池中以进行下一次检索(对象未销毁,因此处置会很糟糕)

如果生活方式是短暂的,则在获取组件时会创建一个新对象。在这种情况下,处置由您决定,您无需调用 Release

如果生活方式是线程,则每个线程使用相同的组件,而不是销毁。

如果生活方式是单例,则只创建一个组件而不会销毁。

最有可能的是,您正在使用瞬态组件?(如果您担心及时处理它们)在这种情况下,只需用 using 包装它就可以了(或在某个地方自己调用 dispose)

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

编辑- 是的,为了“刷新”或处置并重新创建您的单例,您需要销毁容器或编写自定义生命周期。执行自定义生命周期实际上并没有那么困难,并且将执行此操作的逻辑保留在一个地方。

于 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 回答