我有一个Unity IoC容器的简单包装器(临时使用Service Locator [anti-] Pattern将DI引入遗留代码库),并且由于Unity中的IUnityContainer
实现IDisposable
我也希望通过包装器公开它。
包装器很简单:
public class IoCContainer : IIoCContainer
{
private IUnityContainer _container;
public IoCContainer(IUnityContainer container)
{
_container = container;
}
public T Resolve<T>()
{
return _container.Resolve<T>();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~IoCContainer()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
if (_container != null)
{
_container.Dispose();
_container = null;
}
}
}
IIoCContainer
是域名界面,除了T Resolve<T>()
之外什么都没有,当然还有IDisposable
。因此,一种方法下面的所有内容都只是IDisposable
as I found it on MSDN的实现。
但是,当在此对象上调用.Dispose()
时(例如退出using
块时),会引发StackOverflowException
。调试,看起来调用堆栈在:
Dispose()
在此课程中被调用Dispose(true)
Dispose()
IUnityContainer
Dispose()
我可以在这种情况下解决此问题:在类上放置一个bool
标志,在Dispose()
的第一行设置它,并在{{{{}}中检查它1}},所以递归在第二次迭代时结束。但是为什么会发生这种情况呢?我只能假设我错过了一些明显的或者误解了资源处理方面的事情。但是什么?
答案 0 :(得分:4)
这是IDisposable
内UnityContainer
的实施。很明显,您无法处置父容器。如果它们也是IDisposable
,它将遍历所有注册并处理它们。看看:
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (lifetimeContainer != null)
{
lifetimeContainer.Dispose();
lifetimeContainer = null;
if (parent != null && parent.lifetimeContainer != null)
{
parent.lifetimeContainer.Remove(this);
}
}
extensions.OfType<IDisposable>().ForEach(ex => ex.Dispose());
extensions.Clear();
}
}
答案 1 :(得分:2)
我认为这里的问题是你不应该在你的类中处理实现IUnityContainer
的容器实例。
该实例作为资源传递给您的类,但它是在外部创建的,因此无论创建该实例的代码是应该负责正确处理它的实例。
您的IoCContainer
应该只关注处理内部创建的资源。
答案 2 :(得分:2)
这可能不是最佳答案,但如果您无法控制IoCContainer
的实施并且 要处置protected virtual void Dispose(bool disposing)
{
if (disposing)
if (_container != null)
{
var tempContainer = _container;
_container = null;
tempContainer.Dispose();
}
}
,您可以随时打破复活链以至少两种有效的方式:
private bool isDisposed = false;
protected virtual void Dispose(bool disposing)
{
if(isDisposed) return;
isDisposed = true;
if (disposing)
if (_container != null)
{
_container.Dispose();
_container = null;
}
}
或
create table test (col1 string, col2 int, col3 string)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES ("separatorChar" = ",","quoteChar" = "\"")
stored as textfile;