Почему Unity использует локатор служб?

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

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

3 ответов


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

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


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

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

когда вы используете инъекцию зависимостей (например, Unity), тогда да, конечно, не используйте ServiceLocator и используйте только инъекцию конструктора для всех ваших классов обслуживания. (Также не используйте " new " Для чего-либо, кроме объектов value, таких как DTOs.)

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

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

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

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

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

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

IServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => locator);

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