1

I have the following code block for configuring Ninject in my solution:

public class NinjectDependencyScope : IDependencyScope
    {
        private IResolutionRoot resolver;

        internal NinjectDependencyScope(IResolutionRoot resolver)
        {
            Contract.Assert(resolver != null);

            this.resolver = resolver;
        }

        public object GetService(Type serviceType)
        {
            if (resolver == null)
            {
                throw new ObjectDisposedException("this", "This scope has already been disposed");
            }

            return resolver.TryGet(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            if (resolver == null)
            {
                throw new ObjectDisposedException("this", "This scope has already been disposed");
            }

            return resolver.GetAll(serviceType);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                IDisposable disposable = resolver as IDisposable;
                if (disposable != null)
                {
                    disposable.Dispose();
                }

                resolver = null;
            }
        }

My opinion is that disposable pattern used here, is not neccessary..

IDependencyScope is IDisposable, but I should only cleanup IDisposable members if I am constructing them, but the injected resolver in the constructor does is not owned (created) by my class, and IResolutionRoot does not derive from/implement IDisposable...

Am I right here ?

(check this article about IDisposable pattern for reference)

(edit): This is in fact a base class, used by the following class, so removing the IDisposable implementation here cannot be done...

public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
    {
        private IKernel kernel;

        public NinjectDependencyResolver(IKernel kernel)
            : base(kernel)
        {
            this.kernel = kernel;
        }

        public IDependencyScope BeginScope()
        {
            return new NinjectDependencyScope(kernel.BeginBlock());
        }
    }
Patrick Peters
  • 9,456
  • 7
  • 57
  • 106

3 Answers3

1

My experience with Ninject has been that when it comes to managed objects implementing IDisposable, you don't need to worry so much as they will be disposed off eventually.

However, when if you have disposable objects which are wrappers around unmanaged objects (for example a C# class wrapping around an Office Interop Application object), then you need to take greater care as these will be disposed off eventually by Ninject, but you can't reliably say when.

Sometimes you need to clean up these resources quickly, as other parts of your code may rely on these resources being cleaned up already (for example you may be 'using' one of these objects to create a Workbook, and then need to rename the workbook shortly after, by which point you need the Application object to be released).

In this sort of scenario, I may violate DI principle, and just new up the object when I use it, and dispose of it myself.

I guess just test all of this yourself so you know which objects are suitable to use with Ninject, and which aren't and do so accordingly.

JMK
  • 27,273
  • 52
  • 163
  • 280
0

I know that this is the case with Autofac. You shouldn't worry about disposing classes that you have resolved from Autofac because it will call dispose for you. I am pretty sure that Ninject would be similar.

uriDium
  • 13,110
  • 20
  • 78
  • 138
0

The following miminal implimentation is correct (provided that neither this class or a class that derives from it uses UNmanaged resources - which is rarely the case):

public void Dispose() {
    IDisposable disposable = resolver as IDisposable;
    if (disposable != null) {
        disposable.Dispose();
    }
    resolver = null;
}

See Minimal IDispose implementation for details.

It is optional as the resolver will be correctly disposed with out it - i.e only necessary in the case when you particularly need to control yourself the release of the resources managed by the resovler (what?).

Community
  • 1
  • 1
Ricibob
  • 7,505
  • 5
  • 46
  • 65