1

I'm new to DI (using Ninject) and just started to learn the concepts, but I've been scratching my head for a while to understand this:

Suppose I have DIFFERENT usage of the same class in my program (ProcessContext in the example below).

In the first class (SomeClass) : I would like to inject Implement1 to ProcessContext instance.

In the second class (SomeOtherClass) : I would like to inject Implement2 to ProcessContext instance.

How should I perform the bindings using Ninject ?

public class Implement1 : IAmInterace
{
   public void Method()
   {
   }
}

public class Implement2 : IAmInterace
{
   public void Method()
   {
   }
}

public class ProcessContext : IProcessContext
{
   IAmInterface iamInterface;
   public ProcessContext(IAmInterface iamInterface)
   {
      this.iamInterface = iamInterface;
   } 
}

public class SomeClass : ISomeClass
{
    public void SomeMethod()
    {
        // HERE I WANT TO USE: processcontext instance with Implement1
        IProcessContext pc = kernel.Get<IProcessContext>();            
    }
}

public class SomeOtherClass : ISomeOtherClass
{
    public void SomeMethod()
    {
        // HERE I WANT TO USE: processcontext instance with Implement2
        IProcessContext pc = kernel.Get<IProcessContext>();            
    }
}
ohadinho
  • 6,894
  • 16
  • 71
  • 124
  • It sounds like you need something like the [strategy pattern](http://stackoverflow.com/a/32415954/181087) that allows you to select an implementation based on a parameter. Here is another [example](http://stackoverflow.com/a/31971691/181087) that combines the same pattern with an abstract factory to get the instances on the fly. – NightOwl888 Jan 25 '17 at 07:14

3 Answers3

0

You can inject additional constructor parameters easily in this way:

public void SomeMethod()
{
    var foo = new Ninject.Parameters.ConstructorArgument("iamInterface", new Implement2());
    IProcessContext pc = kernel.Get<IProcessContext>(foo);            
}

For now, I don't have access to ninject. So tell me if it doesn't work as expected.

Feriloo
  • 422
  • 2
  • 6
  • In my example I've used only 2 interfaces. What happens "foo" has the same issue ? If Implement2 gets IAmInterface2 in the constructor I would again need to set ConstructorArgument. There isn't an easier way ?? – ohadinho Jan 25 '17 at 06:17
  • @ohadinho In your case you want to pass a concrete type to `IProcessContext`. Actually you don't want to use DI container. But if `Implement2` need some other interface as it's arguments you have to inject the required arguments. I mean usually you get your instance from `Ninject` itself and let `Ninject` to pass parameters to it. – Feriloo Jan 25 '17 at 10:47
0

This is not possible as Ninject has no way of knowing which implementation to return. However; if you create a new instance of your IProcessContext by passing in a variable then Ninject will look for the implementation with the appropriate constructor and return that one.

Michael Puckett II
  • 6,586
  • 5
  • 26
  • 46
0

You could use named bindings for this.

e.g. something like:

Bind<IProcessContext>()
    .To<ProcessContext>()
    .WithConstructorArgument("iamInterface", context => Kernel.Get<Implement1>())
    .Named("Imp1");

Bind<IProcessContext>()
    .To<ProcessContext>()
    .WithConstructorArgument("iamInterface", context => Kernel.Get<Implement2>())
    .Named("Imp2");

kernel.Get<IProcessContext>("Imp1");
Owen Pauling
  • 11,349
  • 20
  • 53
  • 64
  • thank you ! Can you further explain how to do it with SimpleInjector ? – ohadinho Jan 25 '17 at 09:29
  • 1
    @ohadinho Sorry I don't have any experience with SimpleInjector. You should start a new question for that library. – Owen Pauling Jan 25 '17 at 10:28
  • Found out there is a contextbasedinjection in SimpleInjector: http://simpleinjector.readthedocs.io/en/latest/advanced.html#context-based-injection – ohadinho Jan 25 '17 at 13:44
  • This isn't a bad feature and I appreciate you sharing because I too didn't know this existed. But I do feel that it starts to slightly erode the reason to use dependency injection. You're allowing the same interface to have several names and can inject different types into that interface according to various names... However; at some point DI starts to become more maintainable than just referencing types directly. Can anyone help me understand how this becomes a better choice in the long run? Open ears here. – Michael Puckett II Jan 29 '17 at 01:54