Лучшая практика внедрения зависимостей - PullRequest
9 голосов
/ 05 октября 2011

Это вопрос о том, как лучше всего выполнять DI, поэтому он не привязан к какой-либо конкретной структуре DI / IoC, потому что, ну, в общем, среду следует выбирать на основе шаблона и практики, а не наоборот, нет?

Я делаю проект, в котором репозиторий должен быть внедрен в сервисы, сервису может потребоваться несколько репозиториев, и мне интересно узнать о плюсах и минусах следующих подходов:

  1. Внедрение репозиториев в конструктор служб

    public class SomeService : ISomeService
    {
        private IRepository1 repository1;
        private IRepository2 repository2;
    
        public SomeService(IRepository1 repository1, IRepository2 repository2)
        {
              this.repository1 = repository1;
              this.repository2 = repository2;
        }
    
        public void DoThis()
        {
              //Do something with repository1
        }
        public void DoThat()
        {
              //Do something with both repository1 and repository2
        }
    }
    
  2. Внедрение пользовательского класса контекста, который включает все, что может понадобиться любой службе, но создается ленивый (IServiceContext будет защищенным полем в BaseService)

    public class SomeService : BaseService, ISomeService
    {
        public SomeService(IServiceContext serviceContext)
        {
              this.serviceContext= serviceContext;
        }
    
        public void DoThis()
        {
              //Do something with serviceContext.repository1
        }
        public void DoThat()
        {
              //Do something with both serviceContext.repository1 and serviceContext.repository2
        }
    }
    
  3. Внедрить в методы, которые нуждаются только в них

    public class SomeService : ISomeService
    {
        public void DoThis(IRepository1 repository1)
        {
              //Do something with repository1
        }
        public void DoThat(IRepository1 repository1, IRepository2 repository2)
        {
              //Do something with both repository1 and repository2
        }
    }
    

Некоторые указатели будут оценены, более того, какие аспекты я должен рассмотреть воценивать альтернативу, такую ​​как эта?

Ответы [ 3 ]

8 голосов
/ 05 октября 2011

Предпочтительный способ внедрения зависимостей - Конструктор Injection .

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

Обе опции 1 и 2 делают Внедрение в конструктор , что хорошо.Если вам приходится вводить слишком много зависимостей в конструктор, значит что-то не так.Либо вы нарушаете Принцип единой ответственности , либо вам не хватает какого-то агрегированного сервиса , и это то, что вы делаете в варианте 2.

В вашемВ этом случае ваша IServiceContext агрегированная служба группирует несколько репозиториев вместе.Многие репозитории за одним классом для меня пахнут единицей работы .Просто добавьте Commit метод к IServiceContext, и у вас наверняка будет единица работы .Подумайте об этом: не хотите ли вы ввести IUnitOfWork в ваш сервис?

3 голосов
/ 05 октября 2011

Первый вариант представляется наиболее естественным с точки зрения DI. Класс обслуживания требует, чтобы оба репозитория выполняли свою функцию, поэтому создание их для создания экземпляра имеет смысл семантически (и практически).

Второй вариант звучит немного похоже на расположение службы, которое обычно считается антишаблоном (см. http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx).) В двух словах, он создает неявные зависимости, где явные зависимости всегда предпочтительнее.

1 голос
/ 05 октября 2011

Я бы сделал инъекцию на основе конструктора или на основе свойства. Я бы не передавал контекст, содержащий зависимости, если только этот контекст не служит какой-то другой цели.

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

...