My goal is to constructor inject an array of objects implementing an interface.
The following is the way I currently have it.
Container
.Reg
Unity natively understands arrays, so there's no reason to make it so complicated. Just register the ILoaders
you want to include and resolve the object graphs normally. Auto-wiring will take care of the rest:
container.RegisterType<ILoader, FooLoader>("foo");
container.RegisterType<ILoader, BarLoader>("bar");
container.RegisterType<ILoader, BazLoader>("baz");
var c = container.Resolve<MyConsumer>();
assuming that the MyConsumer
constructor is defined like this:
public MyConsumer(ILoader[] loaders)
However, you should be aware that (for some unfathomable reason) Unity only includes named components in this way. The default component:
container.RegisterType<ILoader, Loader>();
will not be included in the array, since it has no name.
Using Resolve
during "configuration time" is acceptable and often useful, and it's perfectly valid for arrays or enumerables.
You could also have done the above by registering the ILoader[]
type and registering each of the specific ILoader
types using the RegisterType
overload that takes a name.
Then, wherever ILoader[]
is required (e.g. needs to be injected), all of the above will resolve for you after configuration time. Of course, if you need multiple/different ILoader[]
it would devolve back to needing to use Resolve
during configuration time.
If you have a slightly more complicated scenario where different arrays of values have to be used in different places, then you can use ResolvedArrayParameter, e.g.
container.RegisterType<ILoader, FooLoader>("foo");
container.RegisterType<ILoader, BarLoader>("bar");
container.RegisterType<ILoader, BazLoader>("baz");
container.RegisterType<ILoader, BooLoader>("boo");
container.RegisterType<IConsumer, MyConsumer>("c1",
new InjectionConstructor(
new ResolvedArrayParameter<ILoader>(
new ResolvedParameter<ILoader>("foo"),
new ResolvedParameter<ILoader>("bar"))));
container.RegisterType<IConsumer, MyConsumer>("c2",
new InjectionConstructor(
new ResolvedArrayParameter<ILoader>(
new ResolvedParameter<ILoader>("baz"),
new ResolvedParameter<ILoader>("boo"))));
var c1 = container.Resolve<MyConsumer>("c1");
var c1 = container.Resolve<MyConsumer>("c2");