С Unity как мне ввести именованную зависимость в конструктор?



У меня есть IRespository зарегистрирован дважды (с именами) в следующем коде:



// Setup the Client Repository
IOC.Container.RegisterType<ClientEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Client", new InjectionConstructor(typeof(ClientEntities)));

// Setup the Customer Repository
IOC.Container.RegisterType<CustomerEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Customer", new InjectionConstructor(typeof(CustomerEntities)));

IOC.Container.RegisterType<IClientModel, ClientModel>();
IOC.Container.RegisterType<ICustomerModel, CustomerModel>();


но тогда, когда я хочу решить это (использовать IRepository) я должен сделать ручное решение, как это:



public ClientModel(IUnityContainer container)
{
this.dataAccess = container.Resolve<IRepository>(Client);

.....
}


то, что я хотел бы сделать, это решить его в конструкторе (так же, как IUnityContainer). Мне нужно каким-то образом сказать, какой именованный тип разрешить.



что-то вроде этого: (примечание: не настоящий код)



public ClientModel([NamedDependancy("Client")] IRepository dataAccess)
{
this.dataAccess = dataAccess;

.....
}


есть ли способ заставить мой поддельный код работать?

479   4  

4 ответов:

вы можете настроить зависимости с именами или без них в API, атрибутах или через файл конфигурации. Вы не упомянули XML выше, поэтому я предполагаю, что вы используете API.

чтобы сообщить контейнеру о разрешении именованной зависимости, вам нужно будет использовать объект InjectionParameter. Для примера ClientModel выполните следующие действия:

container.RegisterType<IClientModel, ClientModel>(
    new InjectionConstructor(                        // Explicitly specify a constructor
        new ResolvedParameter<IRepository>("Client") // Resolve parameter of type IRepository using name "Client"
    )
);

это говорит контейнеру "при разрешении ClientModel вызовите конструктор, который принимает один параметр IRepository. При разрешении этот параметр, решить с именем "клиент" в дополнение к типу."

Если вы хотите использовать атрибуты, ваш пример почти работает, вам просто нужно изменить имя атрибута:

public ClientModel([Dependency("Client")] IRepository dataAccess)
{
   this.dataAccess = dataAccess;

   .....
}

это очень поздний ответ, но вопрос все-таки появился в Google.

так или иначе, 5 лет спустя...

у меня довольно простой подход. Обычно, когда вам нужно использовать "именованную зависимость", это потому, что вы пытаетесь реализовать какой-то шаблон стратегии. В этом случае я просто создаю уровень косвенности между Unity и остальной частью моего кода под названием StrategyResolver чтобы не зависеть напрямую от Единство.

public class StrategyResolver : IStrategyResolver
{
    private IUnityContainer container;

    public StrategyResolver(IUnityContainer unityContainer)
    {
        this.container = unityContainer;
    }

    public T Resolve<T>(string namedStrategy)
    {
        return this.container.Resolve<T>(namedStrategy);
    }
}

использование:

public class SomeClass: ISomeInterface
{
    private IStrategyResolver strategyResolver;

    public SomeClass(IStrategyResolver stratResolver)
    {
        this.strategyResolver = stratResolver;
    }

    public void Process(SomeDto dto)
    {
        IActionHandler actionHanlder = this.strategyResolver.Resolve<IActionHandler>(dto.SomeProperty);
        actionHanlder.Handle(dto);
    }
}

Регистрация:

container.RegisterType<IActionHandler, ActionOne>("One");
container.RegisterType<IActionHandler, ActionTwo>("Two");
container.RegisterType<IStrategyResolver, StrategyResolver>();
container.RegisterType<ISomeInterface, SomeClass>();

теперь, хорошая вещь об этом является то, что мне никогда не придется прикасаться к StrategyResolver когда-либо снова при добавлении новых стратегий в будущем.

это очень просто. Очень чистый, и я сохранил зависимость от Unity до строгого минимума. Единственный раз, когда я коснусь StrategyResolver, - это если я решу изменить контейнерную технологию, что очень маловероятно случаться.

надеюсь, что это помогает!

Edit: мне не очень нравится принятый ответ, потому что когда вы используете Dependency атрибут в конструкторе вашего сервиса у вас на самом деле есть жесткая зависимость от Unity. Элемент Dependency атрибут является частью Библиотеки Unity. В этот момент Вы могли бы также передать IUnityContainer зависимость везде.

Я предпочитаю, чтобы мои классы обслуживания зависели от объектов, которыми я полностью владею, вместо того, чтобы иметь жесткую зависимость от внешнего библиотеки все на месте. Также с помощью Dependency атрибут делает подписи конструкторов менее чистыми и простыми.

кроме того, этот метод позволяет разрешать именованные зависимости во время выполнения без необходимости жестко кодировать именованные зависимости в конструкторе, в файле конфигурации приложения или использовать InjectionParameter которые являются все методы, которые требуют знать, что именованная зависимость для использования во время разработки.

редактировать (2016-09-19): Для тех, кто может задаться вопросом, контейнер будет знать, чтобы передать себя, когда вы запрашиваете IUnityContainer как зависимость, как показано в StrategyResolver подпись конструктора.

вы должны быть в состоянии использовать ParameterOverrides

var repository = IOC.Container.Resolve<IRepository>("Client");
var clientModel = IOC.Container.Resolve<ClientModel>(new ParameterOverrides<ClientModel> { {"dataAccess", repository } } );

изменить: Я не уверен, почему вы передаете UnityContainer-лично мы вводим наши зависимости в сам конструктор (что является "нормальным" из того, что я видел). Но независимо от этого вы можете указать имя в своем RegisterType и разрешить методы.

IOC.Container.RegisterType<IRepository, GenericRepository>("Client");
IOC.Container.Resolve<IRepository>("Client");

и это даст вам тип, который вы зарегистрировали для этого имени.

Не делайте этого - просто создайте class ClientRepository : GenericRepository { } и использовать систему типов.

Comments

    Ничего не найдено.