处置托管资源时的堆栈溢出

Dav*_*vid 7 .net c# stack-overflow idisposable unity-container

我有一个Unity IoC容器的简单包装器(临时使用Service Locator [anti-] Pattern将DI引入遗留代码库),并且由于IUnityContainer在Unity实现中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;
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

IIoCContainer是域接口,除了T Resolve<T>()它之外什么也没有,当然IDisposable.因此,在一种方法下面的所有内容都只是IDisposable 我在MSDN上找到它的实现.

但是,当.Dispose()在此对象上调用时(例如退出using块时),StackOverflowException会引发a.调试,看起来调用堆栈重复:

  • Dispose() 在这堂课上被召唤
  • 哪个打电话Dispose(true)给这个班级
  • 这就要求Dispose()对IUnityContainer
  • 哪个打电话Dispose()给这个班级

在此输入图像描述

在这种情况下,我可以通过bool在类上放置一个标志,在第一行设置它Dispose()并检查它来解决这个问题Dispose(bool),因此递归在第二次迭代时结束.但为什么这首先发生呢? 我只能假设我要么错过了一些明显的东西,要么误解了有关资源处置的问题.但是什么?

Joh*_*nny 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(); 
   } 
} 
Run Code Online (Sandbox Code Playgroud)