Inject Array of Interfaces in Ninject
This is largely a restatement of @bsnote's answer (which I've +1d) which may help in understanding why it works in this manner.
Ninject (and other DI / addin frameworks) have two distinct facilities:
- the notion of either binding to a single unambiguous implementation of a service (
Get
) - A facility that allows one to get a set of services [that one then programmatically picks one of or aggregates across in some way] (
GetAll
/ResolveAll
in Ninject)
Your example code happens to use syntax that's associated with 2. above. (e.g., in MEF, one typically use [ImportMany]
annotations to make this clear)
I'd need to look in the samples (look at the source - its really short, clean and easy to follow) to find a workaround for this.
However, as @bsnote says, one way of refactoring your requirement is to wrap the array either in a container, or to have an object that you ask for it (i.e., a factory method or repository type construct)
It may also be useful for you to explain what your real case is - why is there a naked array ? Surely there is a collection of items construct begging to be encapsulated underlying all this - this question certainly doesnt come up much?
EDIT: There are a set of scanning examples in the extensions that I imagine would attack a lot of the stuff you're trying to do (In things like StructureMap, this sort of stuff is more integrated, which obviously has pros and cons).
Depending on whether you're trying to achieve convention over configuration or not, you might want to consider sticking a marker interface on each type of plugin. Then you can explicitly Bind
each one. Alternately, for CoC, you can make the Module
's Load()
routine loop over the set of implementations you generate (i.e., lots of individual Get
s) in your edit.
Either way, when you have the multiple registrations in place you can happily either 'request' a T[]
or IEnumerable<T>
and get the full set. If you want to achieve this explicitly (i.e., Service Locator and all it implies - like in you're doing, you can use GetAll
to batch them so you're not doing the looping that's implicit in the way you've done it.
Not sure if you've made this connection or if I'm missing something. Either way, I hope it's taught you to stick some code into questions as it speaks > 1000 words :P
It was a problem for me as well. Ninject injects each item of an array instead of the array itself, so you should have a mapping defined for the type of array items. Actually there is no possibility to map the array as a type with the current version of Ninject. The solution is to create a wrapper around the array. Lazy class can be used for example if it suits you. Or you can create your own wrapper.
Ninject supports multi injection which would resolve your issue. https://github.com/ninject/ninject/wiki/Multi-injection
public interface IFoo { }
public class FooA : IFoo {}
public class FooB : IFoo {}
public class Bar
{
//array injected will contain [ FooA, FooB ]
public Bar(IFoo[] foos) { }
}
public class MyModule : NinjectModule
{
public override void Load()
{
Bind<IFoo>().To<FooA>();
Bind<IFoo>().To<FooB>();
//etc..
}
}