我有一个实现 IDisposable 的对象,该对象已在 Windsor 容器中注册,我想处置它,以便调用它的 Dispose 方法,并且下次调用 Resolve 时它会获取一个新实例。

container.Release(obj); 

立即自动调用Dispose()?或者我需要做什么

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

在文档中找不到有关 Release 的具体用途的任何内容

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

有帮助吗?

解决方案

我认为人们在使用 Windsor 容器时并没有真正意识到这一点 - 尤其是经常使用的 奇怪 一次性瞬态组件在内核的生命周期内被容器保留的行为,直到它被处置,除非您自己释放它们 - 尽管有记录 - 看看 这里 - 但快速引用:

Microkernel具有可插入的释放政策,可以连接并实施一些处理组件的路由。MicroKernel 附带了三个 IReleasePolicy 实现:

  • 所有组件发布策略:跟踪所有组件以强制对 MicroKernel 实例处置进行正确处置
  • LifecycledComponentsReleasePolicy:仅跟踪与退役生命周期相关的组件
  • 无跟踪发布政策:不执行任何跟踪

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

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

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

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

其他提示

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

如果生活方式是池化的,您将使用 Release()。这会将组件放回池中以供下次检索(该对象不会被破坏,因此处置会很糟糕)

如果生活方式是瞬态的,则在获取组件时会创建一个新对象。在这种情况下,处置取决于您,并且您不需要调用 Release

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

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

最有可能的是,您正在使用瞬态组件?(如果您担心及时处理它们)在这种情况下,只需将其包裹起来,然后将其设置为设置(或在某个地方称呼自己)

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

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

好吧,所以我一直在运行测试,看起来像 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

幸运的是,就我而言,我可以只删除所有组件,并且可以相当轻松地恢复它们。然而,这是次优的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top