Одна причина для добавления, вдохновленная обновлением документации, которое мы написали для проекта MEF на прошлой неделе (я помогаю строить MEF).
Как только приложение составлено из потенциально тысяч компонентов, может быть трудно определить, может ли конкретный компонент быть правильно создан. Под «созданным правильно» я подразумеваю, что в этом примере, основанном на компоненте Foo
, экземпляр IBar
и будет доступен, и что компонент, обеспечивающий его, будет:
- имеет необходимые зависимости,
- не участвовать в каких-либо недопустимых циклах зависимости, а
- в случае MEF предоставляется только с одним экземпляром.
Во втором приведенном вами примере, когда конструктор отправляется в контейнер IoC для получения его зависимостей, единственный способ проверить, что экземпляр Foo
сможет быть правильно создан с действительным конфигурация приложения во время выполнения должна создать его .
У этого есть все виды неуклюжих побочных эффектов во время теста, потому что код, который будет работать во время выполнения, не обязательно будет работать под тестовым набором. Mocks не подойдут, потому что реальная конфигурация - это то, что нам нужно тестировать, а не какая-то настройка во время теста.
Корень этой проблемы - различие, уже вызванное @Jon: внедрение зависимостей через конструктор является декларативным, а во второй версии используется обязательный шаблон Service Locator.
Контейнер IoC, при аккуратном использовании, может статически анализировать конфигурацию среды выполнения вашего приложения, фактически не создавая экземпляров задействованных компонентов. Многие популярные контейнеры предоставляют некоторые варианты этого; Microsoft.Composition , версия MEF для веб-приложений и приложений в стиле Metro .NET 4.5, предоставляет образец CompositionAssert
в вики-документации. Используя его, вы можете написать код вроде:
// Whatever you use at runtime to configure the container
var container = CreateContainer();
CompositionAssert.CanExportSingle<Foo>(container);
(см. этот пример ).
Проверяя составные корни вашего приложения во время тестирования, вы потенциально можете обнаружить некоторые ошибки, которые в противном случае могут просочиться в процессе тестирования позже.
Надеюсь, это интересное дополнение к этому всестороннему набору ответов по теме!