Построение объектов с функциями как средство внедрения зависимостей - PullRequest
1 голос
/ 07 февраля 2011

Я наткнулся на какой-то код, и мне было любопытно, каковы возможные причины, почему так будет.

Существует два конструктора, основной из которых вызывается в коде, а второй используется при тестировании на внедрение зависимостей.Второй конструктор принял функцию, которая возвращает объект, а не экземпляр самого объекта.

MainConstructor()  
:this(() => Factory.Current.GetInstance<IQueryService>()){ 
}

SecondConstructor(Func<IQueryService> getQueryService){
}

Мне было любопытно, какие преимущества вы получите от передачи функции вместо экземпляра.

Ответы [ 3 ]

1 голос
/ 07 февраля 2011

Существует несколько возможных преимуществ для выполнения чего-либо подобного:

  1. Разделение : разрешив вызывающей стороне передавать делегат, а не экземпляр, и вызывающий, и вызываемый (в вашем случае создаваемый класс) можно отделить от передаваемого объекта и от это исходит от.
  2. Lazy Acquisition : Передавая делегат, экземпляр можно получить ленивым образом. Другими словами, конструктор может в принципе кэшировать делегат и вызывать его в самый последний момент, только когда экземпляр действительно необходим. Если экземпляр никогда не нужен, он может никогда не быть создан.
  3. Возможность восстановления : передавая делегат, а не экземпляр, класс может кэшировать механизм, используемый для создания службы запросов по требованию. Таким образом, делегат действует как фабрика, позволяя создавать экземпляры типа, необходимые для создания по требованию.
0 голосов
/ 08 февраля 2011

Func<IQueryService> - в этом случае действительно замаскированная абстрактная фабрика.Таким образом, вопрос на самом деле таков: «почему вы хотите использовать фабрику вместо инъекции самого объекта?»

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

Лично мне не нравится использовать Func<T> делегаты в качестве фабрик, потому что это делает ваш код менее явным.Вместо того, чтобы зависеть от Func<IQueryService>, пусть класс зависит от IQueryServiceFactory.Это делает ваш код намного более явным.Недостатком этого подхода, конечно, является то, что вам придется писать больше кода (не много, но все же).

Второй конструктор использует шаблон внедрения зависимостей.Первый конструктор, однако, является примером DI для бедняков.Это способ внедрения зависимостей для модульного тестирования, но избавляет вас от необходимости использовать инфраструктуру внедрения зависимостей для вашего производственного кода.Недостатком этого подхода является необходимость зависимости от контейнера (класс Factory в вашем случае), который называется Service Locator .Другим недостатком является то, что он делает необходимые зависимости класса менее очевидными.

0 голосов
/ 07 февраля 2011

Использование Func<T> позволяет лениво создавать продукт, что полезно для необязательных зависимостей - например, один из методов классов может выглядеть так:создать это может повысить эффективность, если someCondition никогда не оценивается как true.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...