Search code examples
c#.netunity-containerstack-overflowidisposable

Stack Overflow when Disposing a Managed Resource


I have a simple wrapper for a Unity IoC container (a temporary use of Service Locator [anti-]Pattern to introduce DI to a legacy codebase), and since the IUnityContainer in Unity implements IDisposable I wanted to expose that through the wrapper as well.

The wrapper is simple enough:

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 is the domain interface which has nothing but T Resolve<T>() on it, and of course IDisposable. So everything below that one method is simply the implementation of IDisposable as I found it on MSDN.

However, when .Dispose() is called on this object (such as when exiting a using block), a StackOverflowException is raised. Debugging, it looks like the call stack repeats between:

  • Dispose() is called on this class
  • Which calls Dispose(true) on this class
  • Which calls Dispose() on IUnityContainer
  • Which calls Dispose() on this class

enter image description here

I can resolve this in this case by putting a bool flag on the class, setting it on the first line of Dispose(), and checking for it in Dispose(bool), so the recursion ends at its second iteration. But why does this happen in the first place? I can only assume I've either missed something obvious or misunderstood something about resource disposal. But what?


Solution

  • This is implementation of IDisposable within UnityContainer. It is obvious that you cannot dispose your parent container. It will iterate through all registrations and dispose them if they are also IDisposable. Take a look:

    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(); 
       } 
    }