Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Still need help understanding why Ninject might be better than manual DI

This is an extension to the question Why do I need an IoC container as opposed to straightforward DI code?

I've been learning Ninject and came up with the following example, the example goes through the manual way of doing DI and the Ninject way of doing DI:

class Program
{
    static void Main(string[] args)
    {
        NinjectWay();
        ManualWay();
        Console.ReadKey();
    }

    private static void ManualWay()
    {
        Console.WriteLine("ManualWay***********************");
        IWeapon sword = new Sword();
        Samurai samurai = new Samurai(sword);

        Console.WriteLine(samurai.Attack("ManualWay..."));

        // change weapon
        IWeapon dagger = new Dagger();
        samurai.Weapon = dagger;

        Console.WriteLine(samurai.Attack("ManualWay..."));

        IWeapon weapon = new Shuriken();
        IWarrior ninja = new Ninja(weapon);
        Console.WriteLine("Manual way.. inject shuriken when a ninja. " + ninja.Weapon.Name);

        IWarrior ninja2 = new Ninja(weapon);
    }

    private static void NinjectWay()
    {
        Console.WriteLine("NinjectWay***********************");
        IKernel kernel = new StandardKernel();
        kernel.Bind<IWeapon>().To<Sword>();
        var samurai = kernel.Get<Samurai>();

        Console.WriteLine(samurai.Attack("NinjectWay..."));

        kernel.Rebind<IWeapon>().To<Dagger>();
        samurai = kernel.Get<Samurai>();

        Console.WriteLine(samurai.Attack("NinjectWay..."));

        kernel.Bind<IWeapon>().To<Shuriken>().WhenInjectedInto<Ninja>();
        var ninja = kernel.Get<Ninja>();
        ninja.OffHandWeapon = new ShortSword();

        Console.WriteLine("Conditional Injection..."+ninja.Weapon.Name);
        Console.WriteLine("Conditional Injection: OffhandWeapon = " + ninja.OffHandWeapon.Name);

        var ninja2 = kernel.Get<Ninja>();
        Console.WriteLine("Conditional Injection..." + ninja2.Weapon.Name);
        Console.WriteLine("Conditional Injection: OffhandWeapon = " + ninja2.OffHandWeapon.Name);

        Console.WriteLine("");
    }
}

I hear the benefits happen when the scale of the project increases but I'm not seeing it. Help me understand this better. Provide more examples in C#/Ninject and help me understand where the benefits really become apparent.

like image 649
Seth Avatar asked Apr 06 '11 12:04

Seth


1 Answers

Unlike the other answers suggest Ninject isn't mainly about making your code more testable. It's Dependency Injection that makes your code more testable! Dependency Injection can be used without an IoC container by creating everything in facotries. But sure, beeing able to replace some parts easily for Integration Tests (don't use Ninject in unit tests) is a nice side effect.

IoC containers like Ninject are mainly about putting your classes together to a working software. In small projects this can easily be done using some factories. But as your application grows the factories get more and more complicated. Imagine an application that has various services some of them are reused others are newly created for every usage. Some of the services are also used by several components.

If you are using a IoC container you have to define exactly once how you get the service instance and what's its lifecycle. On the other hand in a factory you have to specify how you get the instance for every class that needs an instance (e.g. new MyServiceFactory().CreateInstance()). Furthermore, you have to control the lifecycle manually.

This means as the project grows the configuration of an IoC container grows linear together with the project size. But a factory on the other hand grows more exponentional like as there are services that are used throughout the application (e.g. user auth).

BTW: Your example isn't very good because Rebinding isn't a common action. Usually the configuration is done only once at application startup.

like image 85
Remo Gloor Avatar answered Nov 15 '22 13:11

Remo Gloor