Внедрение зависимостей для объектов, которым требуются параметры - PullRequest
8 голосов
/ 04 апреля 2010

Все наши отчеты создаются на основе графов объектов, переведенных с объектов нашего домена. Для этого у нас есть класс Translator для каждого отчета, и мы использовали Dependency Injection для передачи зависимостей.

Это сработало великолепно, и вы получите классы, структурированные так:

public class CheckTranslator : ICheckTranslator
{
   public CheckTranslator (IEmployeeService empSvc
                         , IPaycheckService paySvc)
   {
      _empSvc = empSvc;
      _paySvc = paySvc;
   }

   public Check CreateCheck()
   {
      //do the translation...
   }
}

Однако в некоторых случаях отображение имеет много различных параметров группировки. В результате c-tor станет смесью классов и параметров.

public class CheckTranslator : ICheckTranslator
{
   public CheckTranslator (IEmployeeService empSvc
                         , IPaycheckService paySvc
                         , bool doTranslateStubData
                         , bool doAttachLogo)
   {
      _empSvc = empSvc;
      _paySvc = paySvc;
      _doTranslateStubData = doTranslateStubData;
      _doAttachLogo = doAttachLogo;
   }

   public Check CreateCheck()
   {
      //do the translation...
   }
}  

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

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

1 Ответ

13 голосов
/ 04 апреля 2010

Снимок сделан в темноте, но не могли бы вы вместо этого переместить эти параметры в метод?

Другими словами:

public Check CreateCheck(bool doTranslateStubData, bool doAttachLogo)
{
   //do the translation...
}

Имеют ли эти параметры значение для передачи через конструктор?

(Примечание. Если ваш ответ на этот вопрос «слишком много методов для практического применения», то часть проблемы может заключаться в том, что абстракция слишком грубая).


Другой вариант (действительно трудно сказать без понимания модели предметной области и шаблонов внедрения) - ввести объект параметра, которым сам управляет инжектор:

public interface ICheckConfiguration
{
    bool AttachLogo { get; }
    bool TranslateStubData { get; }
}

Затем введите это с помощью конструктора:

public CheckTranslator (IEmployeeService empSvc, IPaycheckService paySvc,
    ICheckConfiguration config)
{
    // etc.
}   

Этого должно быть достаточно. Затем вы можете создать конкретный класс CheckConfiguration, который принимает эти два свойства bool в своем конструкторе, и настроить свой контейнер для создания различных экземпляров объекта параметра (интерфейса) на основе параметра DI более высокого уровня.


Последнее, что я должен упомянуть, это то, что использование DI не означает, что все должно управляться контейнером. Не так уж плохо создавать CheckTranslator объекты специальным образом, если есть только один вид «переводчика». Пока переводчик по-прежнему зависит от абстракций , что он делает здесь, то, возможно, вам вообще не следует вводить его, просто позвольте классам с поддержкой DI более высокого уровня создавать их ad-hoc.

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