views:

295

answers:

4

I'm using Ninject to retrieve my DataContext from the kernel and I was wondering if Ninject automatically disposes the DataContext, or how he handles the dispose() behaviour. From own experiences I know disposing the datacontext is pretty important and that whenever you create a direct object of the DataContext (as in: new DataContext()) you should use a using() block.

My question thus is: When im retrieving my DataContext from the kernel, should I still have to use a using() block? Or does Ninject fix this for me?

A: 

NInject has no way of knowing when to dispose the DataContext, so you should configure the DataContext with the transient lifetime, thus creating a new context on each call to the kernel. Then you can wrap the usage within a using block and properly dispose the DataContext.

Steven
If your using ninject2 and not using transient scope, wouldn't the datacontext be disposed on deactivation? Which will happen but you don't know exactly when.Looking at the sources this should happen in DisposableStrategy, which is called by the pipeline.
JJoos
The way this is expressed is slightly misleading (evne if the dvice may on the whole prove useful). See http://kohari.org/2009/03/06/cache-and-collect-lifecycle-management-in-ninject-20/
Ruben Bartelink
A: 

Doesn't look like ninject has any sort of lifetime management. This question sheds more light on it.

Perhaps you can investigate implementing your own behaviour like shown in this blog. I haven't tried it but maybe you can make something along the lines of per request singleton with the older instance being disposed when the new one is created.

Igor Zevaka
http://kohari.org/2009/03/06/cache-and-collect-lifecycle-management-in-ninject-20/
Ruben Bartelink
The cited blog is very Ninject 1 specific
Ruben Bartelink
+3  A: 

I am investigating this for my colleague Bas. I was looking in the Ninject 2 source code (http://github.com/ninject/ninject.git), and there seems to be some life cycle management.

When there's an other scope than transient, then the garbage collection of that scope will trigger the deactivation (through the pipeline) of all instances linked to that scope. On deactivation one of the default strategies is DisposableStrategy, this strategy will dispose the instance if it's IDisposable!

I saw a lot of answers on stackoveflow that Ninject doesn't do any life cycle management, maybe this was true for a previous version of Ninject?

But this behaviour is quite tricky, since when using injected services you are not aware of the scope. Because of that you don't know if you have to dispose the object yourself (transient) or that Ninject will take care of this.

Changes to the scope of a service could therefor introduce bugs.

JJoos
I think it's sort of described here by Nate :] http://kohari.org/2009/03/06/cache-and-collect-lifecycle-management-in-ninject-20/
Bas
+1  A: 

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();
Ian Davis
I don't get this feature, why not just use a using block with a kernel.get<>()?What is the benefit of using the activation block?
JJoos
Because all instances retrieved from the block go out of scope. In this example I only showed one instance retrieved. Any singletons retrieved from the block will resolve as singletons. This is true for the other lifestyles as well.
Ian Davis