Reputation: 17186
My goal is to constructor inject an array of objects implementing an interface.
The following is the way I currently have it.
Container
.RegisterInstance<Company>(ParseCompany(args[1])
.RegisterInstance<eTargets>(ParseTargets(args[2]))
.RegisterInstance<ILoader[]>(new ILoader[] {
Container.Resolve<CustomerLoader>(),
Container.Resolve<PaymentLoader(),
Container.Resolve<InvoiceLoader()
});
Is it typical to call Resolve in container configuration this way or is there a more standard way to accomplish the same thing?
Upvotes: 11
Views: 7296
Reputation: 8156
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");
Upvotes: 4
Reputation: 233135
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.
Upvotes: 30
Reputation: 21709
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.
Upvotes: 3