3
votes

I'm researching IoC containers, and have come across an issue when using NInject.

When I have an interface, and I define several mappings of that interface - one not named, my default mapping, and two more named instance - using Microsoft Unity, I nicely get the registered default type when asking Unity to resolve the interface without specifying a name.

Unity:

myContainer.RegisterType<ILogger, DefaultLogger>();
myContainer.RegisterType<ILogger, FastLogger>("fast");
myContainer.RegisterType<ILogger, DatabaseLogger>("dblogger");

var result = myContainer.Resolve<ILogger>();

Here, result will be of type DefaultLogger - as I would have expected (and Autofac also works this way).

Other containers behave differently - some in quite weird ways. And NInject just causes an exception:

k.Bind<ILogger>().To<DefaultLogger>();
k.Bind<ILogger>().To<FastLogger>().Named("fast");
k.Bind<ILogger>().To<DatabaseLogger>().Named("dblogger");

var result = k.Get<ILogger>();

Instead of getting an instance of DefaultLogger as I had expected, I'm getting an exception:

Ninject.ActivationException was unhandled
Message=Error activating ILogger
More than one matching bindings are available.

Yes - I know I have multiple mappings - but I expected that I would get the non-named mapping when specifically not asking for a named mapping.....

Can I get this to work in NInject? Or do I just have to name all mappings and ask for a named mapping even for the default case?

1
You can get this to work, but not by using .Named(). Named must match, there is no default resolution support. However there's the .When(...) kind of bindings which support fallback (default) resolution. I'll post an example later. - BatteryBackupUnit

1 Answers

0
votes

This works

class Program
{
  static void Main(string[] args)
  {
    var kernel = new StandardKernel();

    kernel.Bind<IOperation>().To<DefaultOperation>()
    .When(c => !c.Parameters.Any());

    kernel.Bind<IOperation>().To<SuccessOperation>()
    .Named("Success");

    kernel.Bind<IOperation>().To<FailureOperation>()
    .Named("Failure");

    var operation = kernel.Get<IOperation>();
    operation.ShowMessage();
    Console.ReadLine();
  }
}