Инъекционные массивы с Unity
Моя цель - построить инжектор массива объектов, реализующих интерфейс.
Ниже приводится способ, которым я в настоящее время пользуюсь.
Container
.RegisterInstance<Company>(ParseCompany(args[1])
.RegisterInstance<eTargets>(ParseTargets(args[2]))
.RegisterInstance<ILoader[]>(new ILoader[] {
Container.Resolve<CustomerLoader>(),
Container.Resolve<PaymentLoader(),
Container.Resolve<InvoiceLoader()
});
Является ли типичным для вызова Resolve в конфигурации контейнера таким образом или есть более стандартный способ выполнить одно и то же?
Ответы
Ответ 1
Единство изначально понимает массивы, поэтому нет причин сделать его настолько сложным. Просто зарегистрируйте ILoaders
, который вы хотите включить и разрешить графические объекты. Автоматическая проводка позаботится об остальном:
container.RegisterType<ILoader, FooLoader>("foo");
container.RegisterType<ILoader, BarLoader>("bar");
container.RegisterType<ILoader, BazLoader>("baz");
var c = container.Resolve<MyConsumer>();
предполагая, что конструктор MyConsumer
определяется следующим образом:
public MyConsumer(ILoader[] loaders)
Однако вы должны знать, что (по какой-то непостижимой причине) Unity включает только именованные компоненты таким образом. Компонент по умолчанию:
container.RegisterType<ILoader, Loader>();
не будет включен в массив, так как он не имеет имени.
Ответ 2
Использование Resolve
во время "времени конфигурации" приемлемо и часто полезно, и оно отлично подходит для массивов или перечислений.
Вы также могли бы сделать это, зарегистрировав тип ILoader[]
и зарегистрировав каждый из типов ILoader
, используя перегрузку RegisterType
, которая принимает имя.
Затем, где требуется ILoader[]
(например, нужно вставить), все вышеперечисленное будет разрешено для вас после времени настройки. Конечно, если вам нужно несколько/разных ILoader[]
, он будет возвращаться к использованию Resolve
во время настройки.
Ответ 3
Если у вас есть несколько более сложный сценарий, когда разные массивы значений должны использоваться в разных местах, вы можете использовать ResolvedArrayParameter, например.
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");