Reputation: 1388
I have one standard generic class and few classes for some type parameters that extend it with specific logic. Specific classes may be in another assemblies so there are different modules. I have guessed to register implemented generic type in addition to universal generic registration and it works, but I don't know why. How NInject resolve viewer3
in right way, does it take the most specific registration? May be there any problems with singletons? Thanks.
class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel(new StandardModule(), new BoolModule());
var viewer1 = kernel.Get<IViewer<string>>();
var viewer2 = kernel.Get<IViewer<int>>();
var viewer3 = kernel.Get<IViewer<bool>>();
viewer1.Show("abc");
viewer2.Show(123);
viewer3.Show(true);
}
}
interface IViewer<T>
{
void Show(T value);
}
class StandardViewer<T> : IViewer<T>
{
public void Show(T value)
{
Console.WriteLine(value);
}
}
class BoolViewer : IViewer<bool>
{
public void Show(bool value)
{
Console.WriteLine(value ? "yes!" : "no :(");
}
}
class StandardModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IViewer<>)).To(typeof(StandardViewer<>)).InSingletonScope();
}
}
class BoolModule : NinjectModule
{
public override void Load()
{
Bind<IViewer<bool>>().To<BoolViewer>().InSingletonScope();
}
}
And related question. If I want to add some method to BoolViewer
, how to use it when resolve, only by cast?
var viewer3 = kernel.Get<IViewer<bool>>();
((BoolViewer)viewer3).SomeMethod();
Upvotes: 0
Views: 185
Reputation: 11841
Usually if you add multiple bindings for the same type you would use them to inject an array (as per the multi-injection documentation) so no, Ninject doesn't pick the most relevant binding.
You are perhaps confusing that with constructors, where Ninject will apply the rules of constructor injection:
If a constructor has an [Inject] attribute, it is used (but if you apply the attribute to more than one, Ninject will throw a
NotSupportedException at runtime upon detection).If no constructors have an [Inject] attribute, Ninject will select the one with the most parameters that Ninject understands how to
resolve.If no constructors are defined, Ninject will select the default parameterless constructor (assuming there is one).
However, what you have in your case is generic bindings. If you look at the release notes for Ninject 3.0.0 you will see the following feature:
Added: Open generic bindings can be overriden by closed generics for specific types.
Therefore you have a binding using closed generics for bool
, which will instantiate your BoolViewer
. All other requests for an IViewer<>
will use the open generic binding.
Upvotes: 1