Почему Unity использует сервисный локатор? - PullRequest
6 голосов
/ 03 февраля 2012

Я видел эту строку кода в нескольких руководствах по использованию Unity в asp.net mvc3.У меня сложилось впечатление, что Service Locator - это не шаблон, а лучшая практика.Является ли этот локатор службы чем-то иным, чем определенный анти-шаблон, или эта строка кода / эта реализация считается плохой практикой.

Ответы [ 3 ]

12 голосов
/ 23 августа 2013

Старый вопрос, но для блага других:

Хотя я абсолютно согласен с мантрой «Расположение службы - это анти-шаблон», из этого правила, безусловно, есть исключения.

Когда вы используете Dependency Injection (например, Unity), тогда, да, конечно, не используйте ServiceLocator и используйте инжектор конструктора только для всех ваших классов обслуживания. (Также не используйте «new» для чего-либо, кроме объектов значений, таких как DTO.)

Однако есть случаи, когда вы просто не можете использовать инжекцию конструктора, и тогда единственный способ получить доступ к сервису - это использовать обходной путь для непосредственного доступа к вашему контейнеру Unity, и в таких случаях ServiceLocator является хорошим стандартом. способ сделать это. Это тот случай, когда экземпляр класса создается не вами (или, точнее, не экземпляром Unity), а, например, .NET Framework.

Несколько простых примеров того, как может пригодиться ServiceLocator, - это получить доступ к службам, зарегистрированным в вашем контейнере Unity, из:

  1. реализация WCF IEndpointBehavior или IClientMessageInspector
  2. реализация WPF IValueConverter
  3. или вы не обязательно даже хотите получить доступ к «сервисам» из класса, но вы просто хотите написать код, который может быть проверен на единицу, но по какой-то причине класс вообще не может быть установлен (или нет). легко) потому что обычно он создается с помощью .NET Framework, поэтому вы извлекаете свой пользовательский код в класс, который можно тестировать, и разрешаете его в не тестируемом классе с помощью ServiceLocator.

Обратите внимание, что эта строка не идеальна:

ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container));

Свойство ServiceLocator.Current будет выполнять делегат, предоставляемый каждый раз при доступе к Current, т.е. каждый раз будет создаваться новый UnityServiceLocator. Вместо этого вы, вероятно, захотите сделать это:

IServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => locator);
7 голосов
/ 03 февраля 2012

Если вы создаете каркас, который разработан, чтобы быть независимым от контейнера, локатор службы (хотя это должно быть No-Go в приложении) - это дополнительный уровень косвенности, который позволяет вам менять Unity на что-то другое.Кроме того, использование локатора службы не требует использования DI для приложений, использующих эту платформу.

1 голос
/ 03 февраля 2012

Это тот самый антипаттен, о котором говорят люди. Все, что делает эта строка, это устанавливает поставщика локатора служб как экземпляр UnityServiceLocator, то есть для использования реализации Unity ISerivceLocator. При желании вы можете иметь собственную реализацию IServiceLocator и использовать ее вместо UnityServiceLocator.

Использование сервисного локатора считается плохой практикой по разным причинам, перечисленным здесь

...