Инъекционные массивы с 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");