-
Notifications
You must be signed in to change notification settings - Fork 531
Object Scopes
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 ); } }
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:
- Register the
OnePerRequestModule
with IIS (see below for more detail) - Use the Ninject.Web.Mvc or Ninject.Web extensions which can register
OnePerRequestModule
for you. - Create your kernel and destroy it for each request (this is not recommended)
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>
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
Licensed under Apache 2 License
Contents
- Home
- Why Use Ninject
- Getting Started
- Dependency Injection By Hand
- Dependency Injection With Ninject
- Injection Patterns
- Multi Injection
- Object Scopes
- Modules and the Kernel
- Providers, Factory Methods and the Activation Context
- The Activation Process
- How Injection Works
- Contextual Binding
- Conventions-Based Binding