WCF、Unity:拆卸一次性实例
我们已经设置了一个 WCF 服务,它使用 Unity 容器来解析管理 Exchange 2010 Powershell 命令的实例。我们定义了一个 IExchangePowershell 接口,它有一个实现 IDisposable 的具体实现。一段时间后,我们遇到了无法再执行 powershell 命令的问题,因为服务器表示已经打开了太多的 powershell 会话。看来我们从未真正处置过我们的 powershell 实例。具体 Powershell 的 Dispose() 方法将负责关闭运行空间和会话。一旦我在存储库方法中调用它,我们就不会再收到错误了。
((IDisposable)this.powershell).Dispose();
现在我当然不想在每个存储库方法中显式调用 dispose。我认为团结可以解决这个问题。我们的 WCF 实例提供程序执行此操作:
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
container.Teardown(instance);
}
但这并没有真正处理 IExchangePowershell 实例。您知道我如何自动处理这些实例吗?
we've set up a WCF service which uses a Unity Container to resolve instances for managing Exchange 2010 Powershell commands. We defined an IExchangePowershell interface which has a concrete implementation that implements IDisposable. After some time we encountered the problem that we couldnt execute powershell commands anymore since the server said there are already too many powershell sessions open. It seems that we never really disposed of our powershell instances. The Dispose() method of the concrete Powershell would take care of closing the runspace and the session. Once I call this in the repository methods, we don't get the errors anymore.
((IDisposable)this.powershell).Dispose();
Now of course I dont want to explicitly call dispose in every repository method. I thought unity could take care of this. Our WCF Instance Provider does this:
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
container.Teardown(instance);
}
But that doesnt really dispose of the IExchangePowershell instances. Do you have any idea how I could automatically dispose of those instances?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这实际上是 Unity 中众所周知的问题。
TearDown
方法什么也不做。如果您想使用TearDown
,您必须创建自定义容器扩展。我写了一篇关于使用对象生命周期管理器的文章 Unity 中的内容及其对处置的影响。如果您使用默认的
TransientLifetimeManager
或PerResolveLifetimeManager
,Unity 甚至不会跟踪对象的存在,因此无法调用Dispose
。在已解析实例上调用Dispose
的唯一生命周期管理器是ContainerControlledLifetimeManager
(也称为单例)和HierarchicalLifetimeManager
。当生命周期管理器被释放时,Dispose
被调用。您的解决方案是像您已经执行的那样使用强制转换并手动处理
Dispose
,或者切换到HiearchicalLifetimeManager
并为每个传入的 WCF 请求创建新的子容器。每个子容器仅处理单个请求,并将处理具有分层生命周期的已解析实体。还有其他方法,例如 本文围绕 Unity 构建了一个非常复杂的代码,以支持所有已解析对象的处置和
TearDown
。That is actually well known problem in Unity.
TearDown
method does nothing. If you want to useTearDown
you must create custom container extension.I wrote an article about using object lifetimes managers in Unity and their impact on disposing. If you use default
TransientLifetimeManager
orPerResolveLifetimeManager
the Unity will even don't track existence of your objects so it can't callDispose
. The only lifetime managers which callsDispose
on resolved instances areContainerControlledLifetimeManager
(aka singleton) andHierarchicalLifetimeManager
. TheDispose
is called when the lifetime manager is disposed.The solution for you is either use casting and handle
Dispose
manually as you already did or switch toHiearchicalLifetimeManager
and create new subcontainer for each incoming WCF request. Each subcontainer will only handle single request and it will dispose resolved entities with hiearchical lifetime.There are other ways, for example this article builds a very complex code around Unity to support disposing and
TearDown
for all resolved objects.答案取决于您如何统一注册类型/实例。 Teardown 的标准实现根本不执行任何操作。
如果您注册类型,则 Unity 不会存储对其创建的实例的引用 - 由您来管理它的生命周期并处置它。如果您注册实例,则实例生命周期由 unity 管理并保留到您处置容器为止。
下面的链接有助于更好地了解生命周期管理:
http://msdn.microsoft.com/en-us/library/ff648098.aspx
您需要问自己何时您希望处置您的对象。如果您知道何时调用 ReleaseInstance,您不妨调用 IDispose 而不是它。
(抱歉,我不熟悉WCF,所以我不确定在这种情况下提供的实例是什么)
The answer depends on how you register your type / instance with unity. Standard implementation of Teardown does nothing at all.
If you register type then Unity does not store reference to instance it creates - it's up to you to manage it's lifetime and dispose it. If you register instance, then the instance lifetime is managed by unity and is kept until you dispose of the container.
The link below helps to understand a bit better about lifetime management:
http://msdn.microsoft.com/en-us/library/ff648098.aspx
You need to ask yourself when you would like your objects to be disposed. If you know when to call ReleaseInstance, you might as well call IDispose instead of it.
(I'm sorry, I'm not familiar with WCF, so I'm not sure what instance provide is in this context)