Ninject

Rather than spending time doing the "busy work" of creating and connecting your objects by hand (and reworking lots of such boilerplate for a few minutes or hours whenever you change interdependencies between your components), you just get Ninject to figure it out for you.

How Ninject constructs your types for you

 

Ninject doesn't do anything crazy like rewriting all your assemblies and replacing all instances of new with a redirection to it - it simply gets asked (generally implicitly via one of the extensions, e.g., Ninject.Web.Mvc ) to resolve a service. How does it do this? By calling one of the constructors on your type, just like you would if you were doing Dependency Injection By Hand. (It doesn't use Reflection though - it uses .NETexpression compilation/LCG to make it almost as fast as coding it by hand.)

When asked to instantiate an object, Ninject will look at the type's available public constructors and pick the one with the most parameters it knows how to resolve - or the parameterless one if there aren't any suitable ones (there's an attribute that can be used to override this - see Constructor injection for the nitty gritty).

What this means is that in the vast majority of cases you need to do little if anything to theservice classes you want to resolve and have dependencies injected into in order for Ninject to be able to instantiate your objects; you normally don't change your classes or have any need to reference Ninject assemblies, classes, attributes or namespaces.

How Ninject decides what types to use for type and interface/abstract dependencies - type bindings

 

The most common thing you need to do is when the parameter being injected is specified as an interface - in that case we need to let Ninject know which concrete type to use to satisfy the interface. So if we have a service class as follows:-

 

 


class Samurai
{
    readonly IWeapon weapon;
    public Samurai(IWeapon weapon)
    {
        this.weapon = weapon;
    }
 
    public void Attack(string target)
    {
        this.weapon.Hit(target);
    }
}

 

and we want to grab one like this:-

 


IKernel kernel = new StandardKernel();
var samurai = kernel.Get();

 

 

In the above case, Ninject will select the single constructor defined as the one to use. Next, it tries to resolve a value for each of the constructor's arguments - in this case, there is only one argument to resolve: IWeapon. But wait a second… IWeapon is an interface. You can't create an instance of an interface itself, so how does Ninject know what implementation of IWeapon to inject?

This is accomplished through type bindings. A type binding (or just a binding) is a mapping between a service type (generally an interface or abstract class), and an implementation type to be used to satisfy such a service requirement (or instructions for how to decide which one via ToMethod as we'll see later). Bindings are typically expressed via Ninject's fluent interface. For example, to arm our Samurai with a Sword, we could declare the following binding:

Bind<IWeapon>().To<Sword>();

This binding means that whenever Ninject encounters a dependency on IWeapon, it will resolve an instance of Sword and inject it. This dependency resolution process is a recursive one; that is, if Sword has any dependencies of its own, they will also be resolved before the constructor of Samurai is called. (Also, if the dependencies of Sword have dependencies of their own, they will be resolved in turn, and so on.) In this way, Ninject can wire up an entire graph of objects for you, with minimal work on your end. You just need to set up the path, and Ninject will follow it.

The concept of type bindings is common in dependency injection containers / frameworks. However, some existing frameworks rely primarily on XML mapping files to set up the bindings between types. Through its fluent interface, Ninject allows you to take advantage of the features of your language (like type-safety) and your IDE (like IntelliSense and code completion).

Advanced type bindings

 

If you're just trying to get the hang of dependency injection, we suggest skipping straight to the next section on Injection Patterns and coming back here later - this covers advanced aspects and capabilities of the Ninject type binding mechanism. It's only important to understand this if you're going to have extremely complex scenarios or you're trying to compare DI containers having learned another one first.

Using the overloads with Type parameters instead of the generic methods

 

If you prefer, there are equivalent overloads of the Bind<T>() and To<T>() methods that are not generic methods, which can be useful for automating bulk binding of items you are discovering or scanning from other sources, e.g., one could do the binding above as follows instead:-


  Bind(typeof(IWeapon)).To(typeof(Sword));
  

 

Skipping the type binding bit - Implicit self-binding of concrete types

 

TDD and interface-based programming styles often mean you're generally most commonly depending on interfaces. However, if the type you're resolving is a concrete type (like Samurai above), Ninject will automatically create a default association via a mechanism called implicit self binding. It's as if there's a registration like this:

 

 

for every concrete type you ever try to resolve. Bear in mind that only concrete types can be self-bound; abstract types and interfaces won't work (though there are a variety ofNinject extensions available that e.g., allow one to plug in Convention over Configurationbased policies). Or… as with most things in Ninject, you can plug in your own strategy if you have specific requirements (but that customizability isn't in your face until you need it).

Implicit self-bindings are generated in the default Object Scope (we'll discuss that shortly). If necessary, you can override that by adding a binding of your own of the form:

Bind<Samurai>().ToSelf(); // TODO add your rule overrides at the end, e.g. .InSingletonScope();

Registering more than one type binding for a service -contextual binding

 

You can also have multiple bindings for a given service type, controlled by conditions that examine the context in which the instance is being resolved. This is the contextual binding system mentioned earlier, and is the key to unlocking the full power of Ninject. Don't worry, it's discussed in excruciating detail later. :-)

Registering more than one type binding for a service - plugin models

 

In some cases, you want your service to get a list of n related dependencies rather than just one. This is accomplished by performing 0..n type bindings and then having your service type take a parameter of type T[], List<T> or IEnumerable<T>. See Multi Injection for details.

By: admin | Not tagged | Leave comment

Dependency Injection By Hand

07July2015

So what's Ninject all about? First, let's examine the idea of dependency injection by walking through a simple example. Let's say you're writing the next blockbuster game, where noble warriors do battle for great glory. First, we'll need a weapon suitable for arming our warriors.


class Sword
{
    public void Hit(string target)
    {
        Console.WriteLine("Chopped {0} clean in half", target);
    }
}

 

Then, let's create a class to represent our warriors themselves. In order to attack its foes, the warrior will need an Attack() method. When this method is called, it should use itsSword to strike its opponent.

class Samurai


{
    readonly Sword sword;
    public Samurai()
    {
        this.sword = new Sword();
    }
 
    public void Attack(string target)
    {
        this.sword.Hit(target);
    }
}

 

Now, we can create our Samurai and do battle!


class Program
{
    public static void Main()
    {
        var warrior = new Samurai();
        warrior.Attack("the evildoers");
    }
}

As you might imagine, this will print Chopped the evildoers clean in half to the console. This works just fine, but what if we wanted to arm our Samurai with another weapon? Since the Sword is created inside the Samurai class's constructor, we have to modify the implementation of the class in order to make this change.

When a class is dependent on a concrete dependency, it is said to be tightly coupled to that class. In this example, the Samurai class is tightly coupled to the Sword class. When classes are tightly coupled, they cannot be interchanged without altering their implementation. In order to avoid tightly coupling classes, we can use interfaces to provide a level of indirection. Let's create an interface to represent a weapon in our game.


interface IWeapon
{
    void Hit(string target);
}

 

Then, our Sword class can implement this interface:


{
    public void Hit(string target)
    {
        Console.WriteLine("Chopped {0} clean in half", target);
    }
}

 

And we can alter our Samurai class:


class Samurai
{
    readonly IWeapon weapon;
    public Samurai()
    {
        this.weapon = new Sword();
    }
 
    public void Attack(string target)
    {
        this.weapon.Hit(target);
    }
}

 

Now our Samurai can be armed with different weapons. But wait! The Sword is still created inside the constructor of Samurai. Since we still need to alter the implementation of Samurai in order to give our warrior another weapon, Samurai is still tightly coupled toSword.

Fortunately, there is an easy solution. Rather than creating the Sword from within the constructor of Samurai, we can expose it as a parameter of the constructor instead.


class Samurai
{
    readonly IWeapon weapon;
    public Samurai(IWeapon weapon)
    {
        this.weapon = weapon;
    }
 
    public void Attack(string target)
    {
        this.weapon.Hit(target);
    }
}

 

Then, to arm our warrior, we can inject the Sword via the Samurai 's constructor. This is an example of dependency injection (specifically, constructor injection). Let's create another weapon that our Samurai could use:


class Shuriken : IWeapon
{
    public void Hit(string target)
    {
        Console.WriteLine("Pierced {0}'s armor", target);
    }
}

 

Now, we can create an army of warriors:


class Program
{
    public static void Main()
    {
        var warrior1 = new Samurai(new Shuriken());
        var warrior2 = new Samurai(new Sword());
        warrior1.Attack("the evildoers");
        warrior2.Attack("the evildoers");
    }
}

 

This results in the following output to be printed to the console:

Pierced the evildoers armor. Chopped the evildoers clean in half.

This is called dependency injection by hand, because each time you want to create aSamurai, you must first create some implementation of IWeapon and then pass it to the constructor of Samurai. Now that we can change the weapon the Samurai uses without having to modify its implementation, the Samurai class could be in a separate assembly from Sword - in fact, we can create new weapons without needing the source code of theSamurai class!

Dependency injection by hand is an effective strategy for small projects, but as your application grows in size and complexity, it becomes more and more cumbersome to wire all of your objects up. What happens when the dependencies have dependencies of their own? What happens when you want to add a (e.g. caching, tracing to a log, auditing etc.) decorator in front of each instance of a given dependency? You can easily end up spending most of your time creating and wiring together objects, when you could be writing code that adds real value to your software. This is where dependency injection libraries / frameworks like Ninject can help.

By: admin | Not tagged | Leave comment

Ninject Why use it

06July2015

Why use Ninject?

 

Once you break your application into components, you have to glue them back together.IoC containers solve this problem. Rather than writing the wiring code by hand or depending on a bunch of XML to describe how the pieces fit together, Ninject uses a powerful fluent interface. This lets you get the most out of the sharpest tools in your arsenal: your compiler and your IDE.

Why another IoC container?

 

Ninject v1 wasn't the first .NET Dependency Injection container to the party. Ninject 2 wasn't completely backward compatible with v1. Why did we bother to make another one?

First, a number of other frameworks rely on XML configuration files to instruct the framework on how to wire up the components of your application. This has at least the following disadvantages:

  1. Your configuration is more complex and verbose; you often have to trot out the assembly-qualified name for each of your types etc.
  2. It's much easier to break your application through a simple typing mistake.

In comparison, Ninject's default modus operandi is a fluent interface (or if you prefer, an "embedded domain-specific language") to declare type bindings.

Example

 

For example, if you want to indicate that whenever your code requests an instance ofIService, that an instance of ServiceImpl should be returned:

Bind<IService>().To<ServiceImpl>();

Second, many of the other frameworks are rather heavyweight, meaning you need to add several assembly dependencies to your project and/or take dependencies on all sorts of framework assemblies which may or may not be present in your context (think Client Profile etc.). For smaller projects, this can result in "framework bloat". Ninject aims to keep things simple and straightforward.

Third, Ninject introduces an extremely powerful and flexible form of binding calledcontextual binding. Rather than bind based on a string identifier, Ninject is aware of its environment, and can alter the implementation for a given service during activation. For example:


Bind().To().WhenTargetHas();
Bind().To().WhenTargetHas();
class ConsumerA
{
    public ConsumerA([Red] IService service)
    {
        // The "service" argument will be an instance of RedImpl.
    }
}
class ConsumerB
{
    public ConsumerB([Blue] IService service)
    {
        // The "service" argument will be an instance of BlueImpl.
    }
}

 

Light-weight and highly modular framework

 

Ninject is designed from the ground up to be highly modular. Internally, Ninject 2 and 3 rely on an inversion of control container of its own, reducing factory bloat and making extension of the core much simpler. The core assembly .DLL is in the realm of 100K in size.

Taking out the trash

 

Ninject v2 broke backward compatibility with some aspects of v1's API surface. This decision was not taken lightly. The good news is that a large number of antipatterns and cognitive load resulting from having many different ways to do things simply isn't present, making it easier to discover things without  reading a 200 page manual.

That means you get an API that lands you in the pit of success without looking through massive method lists.

It also means the source is:

  1. compact and minimal with no random stuff that nobody remembers the reason for anymore
  2. beautifully consistent
  3. covered in tests which serve as great examples when the documentation isn't helping you
  4. a good example of a modern TDD'd codebase (the tests use net)

The current maintainers understand the size of installed base Ninject has and won't be making any rash choices that'll leave everyone with a big porting task; they're careful about what goes into Core and make sure that anything that isn't demonstrably long-term and core is an extension…

By: admin | Not tagged | Leave comment

Interface Implementation Examples

02July2015

After you have identified an existing interface that would be useful to your component, or defined interfaces of your own, you can implement that interface in classes your components provide.

Suppose you had a BankManager system that included a number of components, each of which provided objects representing accounts, transactions, and business rules. For example, one component might provide a BusinessAccount class, while another provided a PersonalAccount class.

Defining a Standard Interface

 

You might create a standard interface named IAccount, which included PostInterest and DeductFees methods:


// C#
// Code for the IAccount interface module.
public interface IAccount
{
   void PostInterest();
   void DeductFees(IFeeSchedule feeSchedule);
}

 

Notice that the argument of the DeductFees method uses another interface, IFeeSchedule. One would expect this interface to contain methods describing general customer attributes, such as calculating fees for various account transactions, and that it would be implemented by many classes - BusinessAccount, PersonalAccount, PreferredAccount, and so on.

Notice also that there is no code in these methods. IAccount simply defines the interface. Implementation details will vary according to the object that implements the interface.

Implementing the Standard Interface

 

For example, the BusinessAccount class might implement IAccount as follows:


// C#
class BusinessAccount : IAccount
{
   void IAccount.PostInterest()
   {
      // Code to post interest using the most favorable rate.
   }
 
   void IAccount.DeductFees(IFeeSchedule feeSchedule)
   {
      // Code to change a preferred rate for various services.
   }
}

 

Note    An interface is a contract. You must implement all of the properties and methods in the interface. For details, see  Implementing Existing Interfaces.

Implementing the Interface Differently in Another Class

 

By contrast, the PersonalAccount class might implement IAccount, as shown in the following examples:


// C#
class PersonalAccount : IAccount
{
   void IAccount.PostInterest()
   {
      // Calculate interest for a small account and post it.
   }
 
   void IAccount.DeductFees(IFeeSchedule feeSchedule)
   {
      // Calculate how many service interactions the customer
      // has had and charge accordingly.
   }
}

 

Upgrading Applications to Use a New Interface

 

Once you have classes that implement IAccount, you can upgrade your existing applications one by one to use the new, more competitive interface. You can access the PostInterest and DeductFees methods by assigning a BusinessAccount or PersonalAccount object to a variable of type IAccount, as shown in the following examples:


// C#
BusinessAccount business = new BusinessAccount();
IAccount account = business;
account.PostInterest();

 

You can also declare procedure arguments as IAccount, and pass the procedure any object that implements the IAccount interface, as shown in the following examples:


// C#
public void AccountMaintenance(IAccount account, IFeeSchedule feeSchedule)
{
   account.PostInterest();
   account.DeductFees(feeSchedule);
}

The procedure shown above could be called with any account as the first argument, and any fee schedule as the second. The caller of the procedure can use whatever account is most appropriate for the occasion.