Ninject Mini Tutorial – Part 1

What Is Ninject

There are several Inversion of Control (IoC) containers for .NET to pick from (such as Castle Windsor, Structure Map and Microsoft Unity, just to name just a few).  Ninject is one of the newest entries in the arena, but it’s now sufficiently stable at version 2.0.

Ninject tries to focus on “simplicity and ease of use”, removing features that are not deemed necessary (to the point that XML configuration is not offered out-of-the box).

In this and following posts we’ll explore some example of how to use Ninject. I assume that you are somehow familiar with the basic concepts of Inversion of Control and Dependency Injection; if that’s not the case, you should consider having a look at this wikipedia entry (better yet, take some time and read Martin Fowler famous post on the subject).  

Setup

Installing Ninject is quite easy: you simply download the pre-built DLLs it from here. Since Ninject is open source, you can also get the sources from github and build it on your own.

On my Windows machine, I have copied the DLLs on C:\Ninject.

Getting your Feet Wet With Ninject

Once you have Ninject DLLs somewhere on your hard-drive, in order to get started you only need to reference them (typically you only need to reference NInject.dll ). As we said, no XML configuration is required.

Let’s see a few basic examples (the complete source code with unit tests I present in this series are available on github).

"Hello, Ninject”

Suppose we have a fairly simple service to calculate the taxes for a given amount, defined in an ITaxCalculator interface:

decimal CalculateTax(decimal gross);

and a trivial implementation TaxCalculator as follows:

public class TaxCalculator : ITaxCalculator
{
    private readonly decimal _rate;

    public TaxCalculator(decimal rate)              
    {
        _rate = rate;
    }

    public decimal CalculateTax(decimal amount)
    {
        return Math.Round(_rate * amount, 2);
    }
}

Now, one or more classes might need to use an ITaxCalculator implementation to fulfill their responsibility (such as calculating the total price for a shopping cart). We can say that an implementation of ITaxCalculator is a dependency to them.

Like many IoC containers, Ninject uses a central object (which it calls the kernel) to provide concrete implementations of dependencies at run-time. The Standard Kernel is the default implementation of such an object. Let's see it in action:

using (IKernel kernel = new StandardKernel())
{
    kernel.Bind<ITaxCalculator>()
          .To<TaxCalculator>()
          .WithConstructorArgument("rate", .2M);

    var tc = kernel.Get<ITaxCalculator>();
    Assert.Equal(20M, tc.CalculateTax(100M));
}

 

As you can see, through a fluent interface we are instructing the kernel how to bind (resolve) requests for a ITaxCalculator to a TaxCalculator class (a concrete implementation), passing to its constructor a given tax rate (20% in this case).

The example continues showing how a client can retrieve an implementation of the service through the kernel (via the Get() method) and use it.

Some Magic

You might argue that the little example above is far from impressing. So let’s now see Ninject performing something more clever.

Suppose we have a Sale class modeling a ongoing transaction on a ecommerce site. Such a class in our example depends on a ITaxCalculatorto compute the final price of the shopping cart.

public class Sale
{
    private readonly ITaxCalculator taxCalculator;

    public Sale(ITaxCalculator taxCalculator)
    {
        this.taxCalculator = taxCalculator;
    }

    // more stuff....

    public decimal GetTotal()
    {
	// use the tax calculator to calculate the total
    }
}

We might create the sale in the obvious way, based on the preceding example:

kernel.Bind<ITaxCalculator>()
          .To<TaxCalculator>()
          .WithConstructorArgument("rate", .2M);
var sale = new Sale(kernel.Get<ITaxCalculator>());>

More interestingly, it's possible to let Ninject to find out how a Sale should be built based on the binding information it has received:

kernel.Bind<ITaxCalculator>()
          .To<TaxCalculator>()
          .WithConstructorArgument("rate", .2M);
var sale = kernel.Get<Sale>();

Ninject is smart enough to build a Sale class for us taking care of fulfilling the dependencies behind the scenes. This an example of autowiring, a most convenient feature of many IoC containers.

Go to Part 2

kick it on DotNetKicks.com

This entry was posted in .NET, C#, Design and Patterns and tagged , , , , . Bookmark the permalink.
  • Caley W

    I’m going to assume that Ninject also makes using Mock data for testing using Moq or RhinoMocks really simple? I’ve only used Castle Windsor in ASP.NET MVC2, it was nice to be able to load fake data to write tests against without having to obtain live customer data.

  • Anonymous

    There’s an extension called Ninject.Moq (which I haven’t used personally) which should do the same.

    This blog post should help: http://www.teebot.be/2010/03/aspnet-mvc-and-ninject-repository.html

  • Pingback: Tweets that mention Ninject Mini Tutorial - Part 1 | Stefano Ricciardi -- Topsy.com

  • Jigga

    Why You say Ninject has “excellent run-time performance” when the link You provide clearly shows it’s the slowest IoC Container? X axis is time man!

  • Anonymous

    Jigga, a clear oversight on my side. Thank you for pointing that out. I’ll be amending the post.

  • Pingback: Ninject web articles list « Life, Passion and Programming

  • http://pulse.yahoo.com/_7FMZQQC5FINDL6Y7FSJGLDREXY Salman

    Thanks, good post, good starting point to DI!

  • Anonymous

    @Salman, thank you, glad you found it helpful.

  • http://crixo.myopenid.com/ Cristiano

    Traitor! How Dare you…. Windsor rules

    http://www.winfxitalia.com/articoli/architettura/utilizzare-Windsor-Castle-IoC-container.aspx

    Just joking! Great post. I’m really glad we share same passion for IoC container

  • Scott K Fraley

    I’m trying to run your tests using xunit.gui.x86.exe (1.8) and I’m getting the following;

    xUnit.net Test Runner
    —————————
    Error loading assembly:

    Could not load file or assembly ’C:Dev Samplesstefanoric-NINJECTTUTORIAL-acea645UnitTestbinDebugUnitTest.dll’ or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.
    Do I have to rebuild the xUnit.dll, or… ?(I rebuilt the solution in .Net 4.0, which shouldn’t be a big deal as I got no conversion warning when I loaded it in the first place. Hope I’m not being too thick here, but I don’t get what’s wrong.)Thanks.

  • Scott K Fraley

    ARG!  I was being thick.  I went back to the xUnit directory and noticed “xunit.gui.clr4.x86.exe”. (Note the ‘clr4′ part.) D’OH!

  • Anonymous

    You might try changing the reference to XUnit in the UnitTest project to your own xUnit dll and rebuild the solution.

  • Reza

    Hi,

    Looking at the ‘Sale’ example I’m a bit lost and I don’t know how Ninject finds out about the implementation based on the constructor argument condition in the binding.
     I’m in the similar situation while using ASP.NET MVC 3, I’m trying to bind different implementations for an abstract class using Ninject based on constructor argument. However I don’t know how the constructor argument can be set when Ninject does all the wiring.
    Following is my code:

                Bind().To().WithConstructorArgument(“action”, MassChangeActions.Attach);
                Bind().To().WithConstructorArgument(“action”, MassChangeActions.Detach);
                Bind().To().WithConstructorArgument(“action”, MassChangeActions.Transfer);
                Bind().To().WithConstructorArgument(“action”, MassChangeActions.Activate);

    Assuming I inject the instance to the controller, I’m at lost that how to send “action” argument in order Ninject does all the wiring for me.

    Thanks for enlightening me,
    Reza

  • Anonymous

    I am not sure about what you are trying to achieve here. 

    Looking at your code snippet, it seems that you are repeatedly instructing the kernel to bind MassChangeAction to a different instance of MassChangeActivateAction (which I assume extends MassChangeAction). The last line of code (the one where the action is MassChangeActions.Activate) wins.

    This is similar to:
    x = 1;
    x = 2;
    x = 3;
    x = 4;

    where at the end x is obviously equal to 4.
    In my example, the constructor of Sale needs an argument of type ITaxCalculator. Ninject kernel already knows about an ITaxCalculator implementation because we have explicitly set it to be a TaxCalculator.

    So, when we ask for a Sale object, without specifying anything for the constructor, Ninject assumes that he can pass into the constructor the TaxCalculator that we had previously registered.In your case, the constructor seems to be an enum value, and not an interface / abstract class for which you can provide a different implementations.

    Hope this helps.

  • Pingback: Inyección de Dependencia para Tontos | | CodecriticonCodecriticon

  • Adsfasdf

    thank you. why isn’t this stuff on the github wiki… i don’t want to spend an hour finding how an ioc framework should be setup for the first time

  • Pingback: Ninject bind mulitple implementations to an interface | Code and Programming

  • Daniel B

    Finally the book for Ninject:
    Mastering Ninject for Dependency Injection: http://bit.ly/1hbKdGT

  • Pingback: Ninject – Dependency Injection | Akin Family Blog

  • klk

    ioklkl

  • akash

    aakashhhhhhhhhhhhhhhhhh

  • sddddddddddddd

    reffffffffffffffffff