A bit more about Using Ninject 2.2 - factory methods


(Credit: Image used is from http://fav.me/d2pz3om, if the author objects, I'll remove it immedietly)


As I understand it, Ninject 2.3 will have a .Bind<T>().ToFactory() Method. In the mean time, though, what do we do when we need to bind at run time?

Let's say we have a Ninja class, which we want to send off to... well, 'off' someone. The problem is, we don't know, at design time, if the target will be roaming around a snowy area, or somewhere dark. So which Ninja instance will we need? The one who wears white, or the one who wears black clothes?

 

    class Ninja : ISpecialForcesWarrior
    {        
        
private readonly IClothes _clothes;
        
public Ninja(IClothes clothes)
        {
            _clothes = clothes;
        }
 
        
public void SpecialKill(ITarget target)
        {

            Sneak(); //Uses _clothes
            Kill(target);

        }

 

 

In our NinjectModule Implementation, we'll bind a factory method, like so:

 

            Bind<Func<IClothesISpecialForcesWarrior>>().ToMethod(
                context =>
                clothes => Kernel.Get<
ISpecialForcesWarrior>(new ConstructorArgument("clothes", clothes)));

 

What did we do here? We bound a Func from IClothes to ISpecialForcesWarrior, instead of binding the interface directly. Again: this Func will receive the clothes as a parameter at run-time, and will return the correct instance of the ISpecialForcesWarrior.

 

Note: obviously I added the interface ISpecialForcesWarrior just for fun. You can bind the Func from Iclothes to Ninja, if it'll help your understanding.

 

The class that will instantiate the Ninja, the Daimu, will not use the warrior like this:

 

    class Daimu
    {
        
private ISpecialForcesWarrior _specialForcesWarrior;
        
public Daimu(ISpecialForcesWarrior specialForcesWarrior)
        {
            _specialForcesWarrior = specialForcesWarrior;
        }
    }

 

Instead, the Daimu will look like this:

 

    class Daimu
    {
        
private readonly Func<IClothesISpecialForcesWarrior> _specialForcesWarriorFactory;
 
        
public Daimu(Func<IClothesISpecialForcesWarrior> specialForcesWarriorFactory)
        {
            _specialForcesWarriorFactory = specialForcesWarriorFactory;
        }
 

 

 

        private void SendSpecialWarrior()
        {
            
IClothes clothes = new NinjaClothes { Color = NinjaClothesColor.Black };
            
var warrior = _specialForcesWarriorFactory(clothes);
        }

    }