Bind interface to multiple concrete implementation with constructor argument

253 Views Asked by At

I am trying to do contextual binding but not able to bind concrete implementation interface as constructor argument. Ninject version: 3.2.0.0

My structure is as follows:

INotifier 1. XNotifier 2. YNotifier

IPublisher 1. APublisher 2. BPublisher

where as XNotifier and YNotifier takes constructor argument of type IPublisher.

Here is the binding I have:

Bind<INotifier>()
          .To<XNotifier>()
          .When(x => notifictionControl.ToLower() == "xnotification" )
          .WithConstructorArgument("Publisher",ctx=>Kernel.Get<IPublisher>());


        Bind<INotifier>()
        .To<YNotifier>()
        .When(x => notifictionControl.ToLower() == "ynotification" )
        .WithConstructorArgument("Publisher", ctx => Kernel.Get<IPublisher>());

Usage:

 IParameter parameter = new ConstructorArgument("Publisher", publisher);
        var notifier = kernel.Get<INotifier>(parameter);

But getting following error:

Error activating INotifier No matching bindings are available, and the type is not self-bindable.

1

There are 1 best solutions below

0
On

Your sample code is using a local value from the place where the binding is done. I'm speculating that this is wrong = not what you want.

The error occurs because none of the When condition matches at the time when the binding is resolved. Or to put into other words: at the time when Ninject is asked to return an INotifier it will evaluate all the When conditions of the INotifier bindings and then resolve the one that matches.

When conditions should only be used when during runtime sometimes you want to instantiate "A" and other times "B". If during instantiation of the kernel it's already known which to do, then you should adapt your code like so:

if(notifictionControl.ToLower() == "xnotification")
{
    Bind<INotifier>()...
}
else if(notifictionControl.ToLower() == "ynotification")
{
    Bind<INotifier>()...
}
else
{ 
    throw new Exception("invalid config");
}