2

Скажем, у меня есть интерфейс IDependencyResolver:Регистрация МОК контейнер самостоятельно

public interface IDependencyResolver{ 
    T Resolve<T>() where T: class; 
    object Resolve(Type source); 
} 

и реализацию с использованием SimpleInjector:

public class SIDependencyResolver:IDependencyResolver{ 
    private readonly Container _container; 
    public SIDependencyResolver(Container container){ 
     _container = container; 
     _container.Options.DefaultScopedLifestyle = new WcfOperationLifeStyle(); 
     RegisterDependencies(_container, LifeStyle.Scoped); 
    } 
    public T Resolve<T>() where T:class{ 
     return _container.GetInstance<T>(); 
    } 
    public object Resolve(Type source){ 
     return _container.GetInstance(source); 
    } 
    public void RegisterDependencies(Container container, LifeStyle lifeStyle){ 
     //register dependencies + register self 
    } 
} 

Что мне нужно делать, если мне нужна IDependencyResolver вводится в конструктор, который использует шаблон локатора службы? (Да, я знаю ... антишаблон ... но это в стороне)

public class UnitOfWork: IUnitOfWork{ 
    private readonly IDependencyResolver _resolver; 
    public UnitOfWork(IDependencyResolver resolver){ 
     _resolver = resolver; 
    } 
    public IReadRepository<T> Read<T>(){ 
     return _resolver.Resolve<IReadRepository<T>>(); 
    } 
    public IWriteRepository<T> Write<T>(){ 
     return _resolve.Resolve<IWriteRepository<T>>(); 
    } 
} 

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

container.Register<IDependencyResolver, SIDependencyResolver>(LifeStyle.Singleton); 

Прежде всего, это правильный путь (например, в случае сферы WCF, с одноплодным образом жизни), чтобы сделать это, или есть другой способ сделать это?
Во-вторых, правильно ли передать SimpleInjector.Container в конструктор моего зависимогоResolver?

ответ

2

Что мне нужно сделать, если мне нужен IDependencyResolver, введенный в конструктор, который использует шаблон локатора службы? (да, я знаю ... анти-шаблон ... но это в стороне)

Этого нельзя откладывать. Хотя ваш подход к обратному обращению к контейнеру, как вы делаете в своем UnitOfWork, в порядке, использование абстракции (ab) может быть быстро распространено через базу кода в местах, где это абсолютно не нормально.

Использование абстракции IDependencyResolver должно быть ограничено корнем композиции. Но так как корневой каталог уже знает о существовании точной библиотеки DI, которую вы используете, наличие этой абстракции не имеет преимущества, зависящей непосредственно от самого Container.

Так что ваша IUnitOfWork реализация должна быть определена внутри вашего композиция корня и должна выглядеть следующим образом:

private sealed class SimpleInjectorUnitOfWork : IUnitOfWork { 
    private readonly Container _container; 
    public UnitOfWork(Container container){ 
     _container = container; 
    } 
    public IReadRepository<T> Read<T>() => _container.GetInstance<IReadRepository<T>>(); 
    public IWriteRepository<T> Write<T>() => _container.GetInstance<IWriteRepository<T>>(); 
} 

Регистрация может быть сделано следующим образом:

container.RegisterSingleton<IUnitOfWork>(new SimpleInjectorUnitOfWork(container)); 

В прошлом I всегда регистрировал self resolver self как одноэлементный, поэтому не с охваченным образом образом жизни, так как это давало мне проблемы.

Неясно мне, какие проблемы у вас, но одна вещь, которая будет вызывать неприятность установки DefaultScopedLifestyle внутри конструктора, в то время как тип автоматической проводкой контейнером. Гораздо лучше переместить этот вызов из такого конструктора; это делает его гораздо яснее:

var container = new Container(); 
container.Options.DefaultScopedLifestyle = new WcfOperationLifeStyle(); 
+0

Выгода (на мой взгляд) с созданием этой абстракции является то, что мне не нужно, чтобы добавить пакет SimpleInjector в мой слой данных, где добавлен UnitOfWork. Если я захочу изменить мой контейнер IOC на Unity/Ninject/AutoFac/..., мне нужно только создать новую реализацию моего IDependencyResolver. – RubenHerman

+0

Итак, вы предлагаете перенести мой UnitOfWork из моего проекта Data Layer в проект Resendency Resolution, который также содержит мою ссылку на пакет simpleinjector? – RubenHerman

+0

Что я предлагаю, так это то, что вы оставляете абстракцию «IUnitOfWork» точно там, где она есть, и определяете «SimpleInjectorUnitOfWork» на пути запуска приложения, в котором вы настраиваете свой контейнер (это место обычно называется «Root состава»). – Steven

Смежные вопросы