Различные способы внедрения зависимостей в ASP.NET MVC Controllers? - PullRequest
4 голосов
/ 25 июня 2009

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

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

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

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

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

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

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

Ответы [ 3 ]

5 голосов
/ 25 июня 2009

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

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

5 голосов
/ 25 июня 2009

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

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

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

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

яснее, чем

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

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

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

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

4 голосов
/ 25 июня 2009

Когда вы используете второй подход, недостатки:

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

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

...