DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Software Design and Architecture
  3. Security
  4. Ninject Mini Tutorial – Part 2

Ninject Mini Tutorial – Part 2

Stefano Ricciardi user avatar by
Stefano Ricciardi
·
Aug. 01, 12 · Interview
Like (0)
Save
Tweet
Share
9.95K Views

Join the DZone community and get the full member experience.

Join For Free

Go to Part 1

Controlling the Life Cycle of your Objects

In the previous post we did not concern ourselves with the lifecycle of the object returned from Ninject kernel. Ninject provides the following 4 built-in lifecycles (scopes):

  1. Transient (default)
  2. Singleton (only one instance)
  3. Thread (one instance per thread)
  4. Request (one instance per web request).


You can create custom scopes if needed.

Singleton:

using (IKernel kernel = new StandardKernel())
{
    kernel.Bind<ITaxCalculator>()
        .To<TaxCalculator>()
        .InSingletonScope()
        .WithConstructorArgument("rate", .2M);
 
    var tc1 = kernel.Get<ITaxCalculator>();
    var tc2 = kernel.Get<ITaxCalculator>();
 
    Assert.Same(tc1, tc2);
}

Transient:

using (IKernel kernel = new StandardKernel())
{
    kernel.Bind<ITaxCalculator>()
        .To<TaxCalculator>()
        .InTransientScope()
        .WithConstructorArgument("rate", .2M);
 
        var tc1 = kernel.Get<ITaxCalculator>();
        var tc2 = kernel.Get<ITaxCalculator>();
 
        Assert.NotSame(tc1, tc2);
}

More Details on Injection Patterns

With Ninject you can inject:

  1. Constructor parameters
  2. Properties
  3. Methods

Before considering each one in turn, we just need to introduce the [Inject] attribute which may be used to tag constructors, properties and methods requiring injection. Obviously, by tagging constructors, properties or methods, your objects cease to be POCOs.

Constructor Injection

We have already seen an example of constructor injection in Part I when the kernel auto-magically injected an implementation of ITaxCalculator to the Sale Area constructor. In that case, even if we didn't tag the constructor with the [Inject] attribute, the kernel was able to perform the required binding. How?

That was actually a special case: when there is only one constructor available, the tagging is not needed. On the other hand, if there's more than one constructor defined, then then kernel can inject a dependency to only one constructor that needs to have the [Inject] attribute:

public class Sale3
{
    private readonly ITaxCalculator taxCalculator;
 
    public Sale3() { }
 
    [Inject]
    public Sale3(ITaxCalculator taxCalculator)
    {
        this.taxCalculator = taxCalculator;
    }
 
    // other stuff
}

Properties Injection

Instead of passing in the dependencies through the constructor, you can also inject them as properties. Injecting properties is pretty straightforward:

public class Sale2
{
    [Inject]
    public ITaxCalculator TaxCalculator { get; set; }
 
    // implicit default constructor and other stuff...
 
    public decimal GetTotal()
    {
        decimal total = 0M;
        foreach (var item in lineItems)
        {
            total += TaxCalculator.CalculateTax(item.TotalPrice)
                    + item.TotalPrice;
        }
 
        return total;
    }
}

Usage (note that we never explicitely set the TaxCalculator):

using (IKernel kernel = new StandardKernel())
{
    kernel.Bind<ITaxCalculator>()
                  .To<TaxcCalculator>()
                  .WithConstructorArgument("rate", .2M);
 
    var lineItem1 = new SaleLineItem("Gone with the wind", 10M, 1);
    var lineItem2 = new SaleLineItem("Casablanca", 5M, 2);
 
    var sale = kernel.Get<Sale2>(); // property injection!
    sale.AddItem(lineItem1);
    sale.AddItem(lineItem2);
 
    Assert.Equal(24M, sale.GetTotal());
}

There's an important caveat: if you have 2 or more properties injected, the order in which each dependency is injected is not predictable. This might complicate your design, if those dependencies are coupled somehow (e.g. dependency A needs dependency B). For this kind of situations, constructor or method injection is usually preferred.

Methods Injection

Finally, it’s also possible to tag methods for injection. As with constructor parameters, it’s possible to inject more than one value at once.

public class Sale4
{
    private ITaxCalculator taxCalculator;
 
    // other stuff
 
    // method injection, will be called by the kernel
    [Inject]
    public void SetTaxCalculator(ITaxCalculator taxCalculator)
    {
        this.taxCalculator = taxCalculator;
    }
 
    public decimal GetTotal()
    {
        decimal total = 0M;
        foreach (var item in lineItems)
        {
            total += taxCalculator.CalculateTax(item.TotalPrice)
                  + item.TotalPrice;
        }
 
        return total;
    }
}

Usage (note that we never explicitely call the SetTaxCalculator):

using (IKernel kernel = new StandardKernel())
{
    kernel.Bind<ITaxCalculator>()
          .To<TaxCalculator>()
          .WithConstructorArgument("rate", .2M);
 
    var lineItem1 = new SaleLineItem("Gone with the wind", 10M, 1);
    var lineItem2 = new SaleLineItem("Casablanca", 5M, 2);
 
    var sale = kernel.Get<Sale4>(); // method injection!
    sale.AddItem(lineItem1);
    sale.AddItem(lineItem2);
 
    Assert.Equal(24M, sale.GetTotal());
}

Go to Part 1

Injection

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Using JSON Web Encryption (JWE)
  • Apache Kafka vs. Memphis.dev
  • How To Validate Three Common Document Types in Python
  • Handling Automatic ID Generation in PostgreSQL With Node.js and Sequelize

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: