Внедрение массивов с помощью Unity - PullRequest
10 голосов
/ 18 ноября 2011

Моя цель состоит в том, чтобы конструктор внедрил массив объектов, реализующих интерфейс.

Вот способ, которым я в настоящее время обладаю.

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 в контейнереконфигурация таким образом или есть более стандартный способ сделать то же самое?

Ответы [ 3 ]

27 голосов
/ 18 ноября 2011

Unity изначально понимает массивы , поэтому нет причин делать это так сложно.Просто зарегистрируйте ILoaders, который вы хотите включить, и разрешите графы объектов в обычном режиме. Auto-wiring позаботится обо всем остальном:

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>();

будет не включаться в массив, так как у него нет имени.

4 голосов
/ 06 июня 2016

Если у вас есть немного более сложный сценарий, где разные массивы значений должны использоваться в разных местах, тогда вы можете использовать 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");
3 голосов
/ 18 ноября 2011

Использование Resolve в течение «времени конфигурации» является приемлемым и часто полезным, и оно совершенно справедливо для массивов или перечислимых значений.

Вы могли бы также сделать это, зарегистрировав тип ILoader[] и зарегистрировав каждый из определенных типов ILoader, используя перегрузку RegisterType, которая принимает имя.

Тогда, где требуется ILoader[] (например, необходимо ввести), все вышеперечисленное разрешится для вас после времени конфигурации. Конечно, если вам нужно несколько / разное ILoader[], это приведет к необходимости использования Resolve во время настройки.

...