Alex Rivera | Logout

Inject different classes that implement the same interface using Ninject

Asked 2011-12-21T05:09:51.307
11

I am implementing the builder design pattern to construct different kinds of graph objects to be displayed on a WPF UI. I am using Ninject as my IOC container. However, I am trying to find an elegant extendable solution.

I have a ChartDirector object that takes a IChartBuilder as a dependency. I also have TemperatureChartBuilder and ThresholdChartBuilder that implement IChartBuilder. I want to inject either TemperatureChartBuilder OR ThresholdChartBuilder to ChartDirector depending on an event that is fired or depending on a client call. I have illustrated my problem below in code.

// ChartDirector also depends on this
kernel.Bind<IExample>().To<Example>();

// when called in Method X...
kernel.Bind<IChartBuilder>().To<TemperatureChartBuilder>();

// when called in Method Y...
kernel.Bind<IChartBuilder>().To<ThresholdChartBuilder();

// TemperatureChartBuilder is a dependency of ChartDirector, need a way to dynamically
// allocate which binding to use.
var director = kernel.Get<ChartDirector>();

// without Ninject I would do
var director = new ChartDirector(new TemperatureChartBuilder);

// or
var director = new ChartDirector(new ThresholdChartBuilder);

EDIT:

Coupled with Gary's answer, and noting a slight edit that ChartDirector has another dependency, I now want to do something like this:

var director = kernel.Get<ChartDirector>().WithConstructorArgument(kernel.Get<IChartBuilder>("TemperatureChart"));

Is something like this possible?

Edit
Report

1 Answer

15

If you're just planning to use service location, as in your examples, then named bindings work fine, as per Garys answer.

A better approach, however, is to use constructor injection, and use attributes. For exampl, from the ninject wiki:

Bind<IWeapon>().To<Shuriken>().Named("Strong");
Bind<IWeapon>().To<Dagger>().Named("Weak"); 

...

class WeakAttack {
    readonly IWeapon _weapon;
    public([Named("Weak")] IWeapon weakWeapon)
        _weapon = weakWeapon;
    }
    public void Attack(string victim){
        Console.WriteLine(_weapon.Hit(victim));
    }
}

Based on your comment to Gary, you're (strangely enough) stumbling into territory similar to what I asked a question about a few hours ago. See Remo's answer here: Using WithConstructorArgument and creating bound type

You would use When condition to define when to create the correct instance.

answered 2011-12-21T05:34:25.027

Your Answer