Skip to content
remogloor edited this page Feb 20, 2012 · 32 revisions

In many cases, the same instance of a type needs to be used throughout your application. The common way to achieve this goal is via the Singleton pattern. For example:

    sealed class Shogun 
    {
        public static readonly Shogun Instance = new Shogun();
        private Shogun() { }
        public void RuleWithIronFist() 
        {
            ...
        }
    }

The problem with this is you basically have to lock down your type. Doing things this way will make your code end up rigid and inflexible. In particular, it'll be very difficult to unit test code that's implemented this way.

Ninject makes it easy to re-use instances that are already created, without having to implement anything via code. All you need to do is tell Ninject to Bind the class in a singleton scope.

kernel.Bind().ToSelf().InSingletonScope();

Of course, this behavior will only work for instances requested from the kernel. (Resolving instances is explained in the next section.)

There are four built-in scopes available in Ninject:

Scope Binding Method Meaning
Transient .InTransientScope() A new instance of the type will be created each time one is requested. (This is the default scope)
Singleton .InSingletonScope() Only a single instance of the type will be created, and the same instance will be returned for each subsequent request.
Thread .InThreadScope() One instance of the type will be created per thread.
Request .InRequestScope() One instance of the type will be created for each web request. See the section “InRequestScope” below for more information before using this.

If no scope is specified, by default, the StandardKernel will use the Transient scope. This default scoping also applies to implicit self bindings of concrete types

You can also easily define your own scopes using the .InScope(Func<object> o) method. Note that the releasing of instances is subject to the implications of the Cache and Collect system described here

Here's a simple test demonstrating how a custom scope works:

public class ScopeObject { }

public static class ProcessingScope
{
  public static ScopeObject Current {get; set;}
}

using Xunit;
public class NinjectCustomScopeExample
{
  public class TestService { }

  [Fact]
  public static void Test()
  {
    var kernel = new StandardKernel();
    kernel.Bind().ToSelf().InScope( x => ProcessingScope.Current );
    
    var scopeA = new ScopeObject();
    var scopeB = new ScopeObject();
   
    ProcessingScope.Current = scopeA;
    var testA1 = kernel.Get();
    var testA2 = kernel.Get();
    
    Assert.Same( testA2, testA1 );
   
    ProcessingScope.Current = scopeB;
    var testB = kernel.Get();
    
    Assert.NotSame( testB, testA1 );
   
    ProcessingScope.Current = scopeA;
    var testA3 = kernel.Get();
    
    Assert.Same( testA3, testA1 );
  }
}

InRequestScope

For http server applications hosted under IIS, you can use InRequestScope() to have Ninject create a single instance for each http request handled by your application. For InRequestScope() bound instances, Ninject will use HttpContext.Current as the scoping object. Note that you do not have to use InRequestScope() to use Ninject with your http server application - you can use InTransientScope() and even InSingletonScope() if those behaviors are desired. The main reason for using InRequestScope() is to make sure that a single instance of an object is shared by all objects created via the Ninject kernel for that http request (e.g. share an object that is expensive to create).

IMPORTANT

The Ninject kernel maintains a weak reference to scoping objects and will automatically dispose of objects associated with the scoping object when the weak reference to it is no longer valid. Since InRequestScope() uses HttpContext.Current as the scoping object, any associated objects created will not be destroyed until HttpContext.Current is destroyed. Since IIS/.NET manages the lifecycle of HttpContext objects, disposal of your objects is tied to whenever IIS/.NET decides to destroy the HttpContext object and that may not be predictable. To get more deterministic behavior, you can do any of the following:

  1. Register the OnePerRequestModule with IIS (see below for more detail)
  2. Use the Ninject.Web.Mvc or Ninject.Web extensions which can register OnePerRequestModule for you.
  3. Create your kernel and destroy it for each request (this is not recommended)

OnePerRequestModule

OnePerRequestModule is an IHttpModule provided by Ninject that will hook the end request callback and deactivate instances associated with HttpContext.Current in the Ninject kernel for you. You can register it using the following XML in your Web.Config:

<configuration>
  <system.web>
    <httpModules>
      <add name="OnePerRequestModule" type="Ninject.OnePerRequestModule"/>
    </httpModules>
  </system.web>
</configuration>

WCF Support

Ninject 2.2 does not support InRequestScope for WCF based services. Ninject 3.0 does support WCF based services and will scope objects bound with InRequestScope to OperationContext.Current. An example of how to get Ninject integrated with WCF REST services can be found here.

Continue reading: Modules and the Kernel