Различные способы внедрения зависимостей в контроллеры ASP.NET MVC?

StackOverflow https://stackoverflow.com/questions/1044403

Вопрос

В большинстве примеров, которые я видел в Интернете, DI в контроллерах MVC выполняется следующим образом.

public ProductController(IProductRepository Rep)
{
    this._rep = Rep;
}

Используется пользовательский ControllerFactory, который использует выбранную структуру DI и внедряет репозиторий.

Почему вышеперечисленное считается лучше, чем

public ProuctController()
{
    this._rep = ObjectFactory.GetInstance<IProductRepository>();
}

Это даст те же результаты, но не требует создания специальной фабрики контроллеров.

Что касается тестирования, тестовое приложение может иметь отдельный BootStrapper.Таким образом, когда контроллеры тестируются, они могут получить поддельные репозитории, а когда они используются по-настоящему, они получат настоящие.

Это было полезно?

Решение

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

Во-первых, локатор служб скрывает зависимости. Во втором примере, если посмотреть только на общедоступный интерфейс, невозможно узнать, что ProductControllers нужны репозитории.

Более того, мне нужно повторить OdeToCode . Я думаю

IProductRepository repository = Mockery.NewMock<IProductRepository>();
IProductController controller = new ProductController(repository);

яснее, чем

ObjectFactory.SetFactory(IProductRepository, new MockRepositoryFactory())
IProductController controller = new ProductController();

Особенно, если ObjectFactory настроен в методе SetUp тестового устройства.

Наконец, шаблон локатора сервиса явно неоптимален, по крайней мере, в одном конкретном случае: когда вы пишете код, который будет использоваться людьми, пишущими приложения вне вашего контроля. Я держу пари, что люди обычно предпочитают инъекцию конструктора (или один из других методов DI), потому что это применимо для каждого сценария. Почему бы не использовать метод, который охватывает все случаи?

(Мартин Фаулер предлагает гораздо более тщательный анализ в &. Инверсия контейнеров управления и Шаблон внедрения зависимостей & Quot; , особенно раздел & Quot; Локатор служб и внедрение зависимостей & Quot;).

Другие советы

Основным недостатком второго конструктора является то, что ваш контейнер IoC должен быть правильно настроен для каждого теста. Такая настройка может стать настоящим бременем по мере роста базы кода и более разнообразных сценариев тестирования. Тесты, как правило, легче читать и поддерживать, когда вы явно проходите двойной тест.

Другая проблема заключается в подключении огромного количества классов к конкретной структуре DI / IoC. Конечно, есть способы абстрагировать его, но у вас все еще есть замусоренный код для извлечения зависимостей. Так как все хорошие фреймворки могут выяснить, какие зависимости вам нужны, взглянув на конструктор, он & # 8217, требует много усилий и дублирует код.

Недостатками второго подхода являются:

  • Необходимы огромные и нечитаемые методы настройки/контекста тестирования.
  • Контейнер подключен к контроллеру
  • Вам нужно будет написать гораздо больше кода

Почему вы все равно хотите использовать ioc-контейнер, если вам не нужна инъекция зависимостей?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top