Старый вопрос, но для блага других:
Хотя я абсолютно согласен с мантрой «Расположение службы - это анти-шаблон», из этого правила, безусловно, есть исключения.
Когда вы используете Dependency Injection (например, Unity), тогда, да, конечно, не используйте ServiceLocator и используйте инжектор конструктора только для всех ваших классов обслуживания. (Также не используйте «new» для чего-либо, кроме объектов значений, таких как DTO.)
Однако есть случаи, когда вы просто не можете использовать инжекцию конструктора, и тогда единственный способ получить доступ к сервису - это использовать обходной путь для непосредственного доступа к вашему контейнеру Unity, и в таких случаях ServiceLocator является хорошим стандартом. способ сделать это. Это тот случай, когда экземпляр класса создается не вами (или, точнее, не экземпляром Unity), а, например, .NET Framework.
Несколько простых примеров того, как может пригодиться ServiceLocator, - это получить доступ к службам, зарегистрированным в вашем контейнере Unity, из:
- реализация WCF IEndpointBehavior или IClientMessageInspector
- реализация WPF IValueConverter
- или вы не обязательно даже хотите получить доступ к «сервисам» из класса, но вы просто хотите написать код, который может быть проверен на единицу, но по какой-то причине класс вообще не может быть установлен (или нет). легко) потому что обычно он создается с помощью .NET Framework, поэтому вы извлекаете свой пользовательский код в класс, который можно тестировать, и разрешаете его в не тестируемом классе с помощью ServiceLocator.
Обратите внимание, что эта строка не идеальна:
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container));
Свойство ServiceLocator.Current будет выполнять делегат, предоставляемый каждый раз при доступе к Current, т.е. каждый раз будет создаваться новый UnityServiceLocator. Вместо этого вы, вероятно, захотите сделать это:
IServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => locator);