0

I have a follow up question to this question: Is it possible to bind different interfaces to the same instance of a class implementing all of them?

I have a scenario where one of the interface needs to be resolved by the name provided by "Named" extension, and another doesn't need a name to be resolved.

For instance

public interface IMachine { }
public interface IDrillMachine : IMachine { }

public class Drill: IDrillMachine { }
public class ScrewDriver: IMachine { }

Ninject Binding

Bind<IMachine, IDrillMachine>().To<Drill>().Named("Drill");
Bind<IMachine>.To<ScrewDriver>().Named("ScrewDriver");

Injection

public class MachineConsumer
{
    public MachineConsumer([Named("Drill")]IMachine drillMachine)
    { }
}

public class DrillConsumer
{
    public DrillConsumer(IDrillMachine drillMachine)
    { }
}

My code isn't in working condition, so can't test. But I think that at the time of resolving IDrillMachine there will be confusion, isn't it?

Marshal
  • 6,551
  • 13
  • 55
  • 91
  • Not sure if this is the problem, but after looking at the linked question's accepted answer, it looks like you are missing a call to `.InSingletonScope()` in your Ninject bindings. – Lews Therin May 16 '19 at 18:41
  • The only difference adding `.InSingletonScope()` would make is that I will get a single instance, instead of a new instance of `DrillMachine`. The original problem still stays, i.e. will Ninject be able to resolve `IDrillMachine` and give me an instance of `DrillMachine`? – Marshal May 16 '19 at 19:05

1 Answers1

1

That won't work because the DrillConsumer constructor is missing the [Named("Drill")] name specification but the binding for IDrillMachine requires it. Your scenario can be resolved by two separate bindings for Drill:

Bind<IMachine>().To<Drill>().Named("Drill");
Bind<IDrillMachine>().To<Drill>();

It get's a bit more complicated if Drill needs to be a scope object like a singleton. Adding in InSingletonScope() to both bindings will result in two instances, a singleton for IMachine("Drill") and one for IDrillMachine.

To resolve this you can add a level of indirection:

Bind<IMachine>().ToMethod(ctx => ctx.Kernel.Get<Drill>()).Named("Drill");
Bind<IDrillMachine>().ToMethod(ctx => ctx.Kernel.Get<Drill>());
Bind<Drill>().ToSelf().InSingletonScope();
BatteryBackupUnit
  • 12,934
  • 1
  • 42
  • 68
  • Thanks for the answer. To my surprise DrillConsumer got instantiated just fine, and didn't need `[Named("Drill")]` spec to it. – Marshal May 30 '19 at 18:26