1

How to make Ninject to instantiate object based on variable on run time?.

I am trying to inject the correct Repository in The Controller action - MVC 3 - based on parameter come from user input. If user input "BMW" it would bind ICarRepository to BMWRepository , and if he input "KIA" KiaRepository will be injected.

[HttpPost]
public ActionResult SearchResult(FormCollection values)
{
    string carModel  = values["model"];

    ICarRepository myRepository = RepositoryFactory.getRepository(carModel);

    .....
}

This is known by switch/case noob instantiation or Parameterized Factories, and i know how to do it manually without Ninject , Check the 4 approaches explained here Exploring Factory Pattern

My question is how to do it with Ninject?

Ashkan
  • 3,322
  • 4
  • 36
  • 47
user968159
  • 126
  • 1
  • 10
  • Is https://github.com/ninject/ninject.extensions.factory/wiki/Factory-interface%3A-Referencing-Named-Bindings any use for your actual case (probably not) ? – Ruben Bartelink Oct 24 '12 at 21:43

1 Answers1

5

You could inject an Abstract Factory (probably just a Func<string,ICarRepository>) and then have it all implemented via adding the following to your RegisterServices:

Bind<ICarRepository>().To<KiaRepository>().Named("KIA")
Bind<ICarRepository>().To<BmwRepository>().Named("BMW")
Bind<Func<string,ICarRepository>>()
    .ToMethod( ctx=> name => ctx.Get<ICarRepository>( name));

In your ctor:

class MyController
{
    readonly Func<string,ICarRepository> _createRepository;

    public MyController(Func<string,ICarRepository> createRepository)
    {
        _createRepository = createRepository;
    }

Then, in your action:

[HttpPost]
public ActionResult SearchResult(FormCollection values)
{
    string carModel  = values["model"];

     using( ICarRepository myRepository = _createRepository( carModel)) 
     {
            ... 
     } 
}
Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
  • Could you please tell me how to call it from controller Action? – user968159 Oct 25 '12 at 02:11
  • @user968159 you add `Func createRepository` to your arguments, assign it to a `readonly` field, and then do `using( var repo = _createRepository( carModel)) { ... }` – Ruben Bartelink Oct 25 '12 at 07:47
  • Giving That `Func` will be binned to ctx.Get( name) , In IBMWRepository should i decorate it with name attribute and set its value to "BMW"? My understanding to ctx.Get( name) is it passes name to the constructor. – user968159 Oct 28 '12 at 01:53
  • @user968159 No, the way that I'm doing it, the first arg to the func is used to identify the name of the binding. (So you'll need to `Bind().To().Named("KIA")` for ti all to connect up. Edited this in. BTW have you looked at ninject.extensions.factory ? Unless your real problem is exactly as you have asked, most of this kind of stuff is best accomplished with it – Ruben Bartelink Oct 28 '12 at 16:04
  • Yes it Works now, and this is exactly what i am looking for. Thanks alot Ruben – user968159 Oct 28 '12 at 16:12