How do I manage object disposal when I use IoC?

2019-06-22 13:48发布

问题:

My case it is Ninject 2.

// normal explicit dispose
using (var dc = new EFContext) 
{
}

But sometimes I need to keep the context longer or between function calls. So I want to control this behavior through IoC scope.

// if i use this way. how do i make sure object is disposed.
var dc = ninject.Get<IContext>() 

// i cannot use this since the scope can change to singleton. right ??
using (var dc = ninject.Get<IContext>()) 
{
}

Sample scopes

Container.Bind<IContext>().To<EFContext>().InSingletonScope();
// OR
Container.Bind<IContext>().To<EFContext>().InRequestScope();

回答1:

From what I know (I did a research about a month ago) Ninject does not support lifecycle management at all. Castle Windsor and AutoFac (and to some extent StructureMap, but only when using nested containers) will take care of disposing disposable components they create at appropriate time.



回答2:

If you have control over the interface of IContext, add IDisposable to the list of interfaces from which it inherits. If not, downcast the IContext you get to an IDisposable...

var context = ninject.Get<IContext>();

using ((IDisposable)context)
{
}

You also have the option of altering the interface of IContext to do this by composition, if you control IContext...

public interface IContext
{
   // ...

   IDisposable GetUsageHandle();
}

var context = ninject.Get<IContext>();

using (context.GetUsageHandle())
{
}


回答3:

In addition to the standard scopes of Transient, OnePerThread, and Singleton, you can use an ActivationBlock in order to control the lifetime of a whole set of objects. When the block is disposed, all object retrieved by the block go out of scope - so singletons and others are disposed of when their instances are requested by the activation block.

var kernel = new StandardKernel();
kernel.Bind<NotifiesWhenDisposed>().ToSelf();

NotifiesWhenDisposed instance = null;
using(var block = new ActivationBlock(kernel))
{
    instance = block.Get<NotifiesWhenDisposed>();
    instance.IsDisposed.ShouldBeFalse();
}

instance.IsDisposed.ShouldBeTrue();