Ninject 3 multiple bindings

2019-08-07 16:28发布

问题:

My question is really a repeat of an old question posted here: Ninject 2.2 multiple bindings

It seems someone was going to deal with this back in 2011. Does anyone know if there is some way to turn off such warnings in Ninject? Or some other workaround?

EDIT

In response to @BatteryBackupUnit, here is my exact problem:

I have multiple libraries... and in my core library, I do something like this:

  1. Find all assemblies referenced by the host application (including the host)
  2. Find all types inheriting from IDependency from all those assemblies.
  3. Automatically register all of those as transient

Then from another library (which may or may not be referenced by the host app), I have this:

Kernel.Bind<IDbContextFactory>().To<DbContextFactory>().InSingletonScope();

Here IDbContextFactory is also an IDependency, so it got loaded already by the core library and now I register it here but with a different scope (singleton).

From experience (and having tested it earlier) I know this is no problem in Autofac, but Ninject gives me that error message about having already registered it.

Ideally it would be better to just override any previous registrations... "cascade style" (for lack of a better phrase)..

回答1:

Ninject does now support overriding open generic bindings with more specific ones. For Example:

public interface IFoo<T> { }
public class Foo<T> : IFoo<T> { }
public class StringFoo : IFoo<string> {}

used like:

var kernel = new StandardKernel();
kernel.Bind(typeof(IFoo<>)).To(typeof(Foo<>));
kernel.Bind<IFoo<string>>().To<StringFoo>();

var intFooInstance = kernel.Get<IFoo<int>>();
var stringFooinstance = kernel.Get<IFoo<string>>();

Works.

However, if you're not talking about open generic bindings, ninject 3 still handles multi bindings the same as ninject 2.2.

In most scenarios you can work around this by using contextual bindings. Okay i would not exactly call it a workaround, i would call it good design. In general this is described here: https://github.com/ninject/ninject/wiki/Contextual-Binding

A simple way would be to specify the binding using a name. This requires one binding for the specified one and allows only one, too. See: https://github.com/ninject/ninject/wiki/Contextual-Binding#simple-constrained-resolution-named-bindings

It is also possible to define a "default" binding like .Bind<IFoo>().To<Foo>(); and special case bindings with the .When(...) syntax, like:

.Bind<IFoo>().To<SpecialFoo>().When(ctx => ...)

See https://github.com/ninject/ninject/wiki/Contextual-Binding#specifying-constraints-on-the-type-binding-using-arbitrary-elements-of-the-resolution-request-context

If you show us your concrete problem we might be able to provide a more concrete solution.