Когда вы будете использовать Common Service Locator?

Я рассматривал Common Service Locator как способ абстрагирования моего контейнера IoC, но я заметил, что некоторые люди категорически против этого типа.

Люди рекомендуют никогда не использовать это? Всегда используете это? или иногда его используете? Если иногда, то в каких ситуациях вы бы использовали его, а в каких ситуациях вы бы его не использовали.

4 ответа

Решение

Представьте, что вы пишете библиотечный код, который будет использоваться сторонними разработчиками. Ваш код должен иметь возможность создавать сервисные объекты, которые предоставляют эти разработчики. Однако вы не знаете, какой контейнер IoC будет использовать каждый из ваших абонентов.

Общий сервисный локатор позволяет вам справиться с вышеизложенным, не навязывая определенный IoC вашим пользователям.

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

Я заметил, что один из аргументов против использования CSL является ложным, потому что разработчики считают, что эта библиотека способна выполнять только шаблон Service Locator. Это, однако, не так, потому что его легко использовать с шаблоном Dependency Injection.

Тем не менее, библиотека CSL была специально разработана для разработчиков инфраструктуры, которым необходимо разрешить пользователям регистрировать зависимости. Поскольку библиотека будет вызывать CSL напрямую, с точки зрения платформы мы говорим о шаблоне SL, отсюда и его имя.

Однако, как разработчик фреймворка, не следует воспринимать зависимость от CSL легко. Для удобства использования вашей среды обычно лучше иметь собственный механизм DI. Очень распространенным механизмом является установка зависимостей в файле конфигурации. Этот шаблон используется во всей платформе.NET. Почти каждая зависимость может быть заменена на другую. Шаблон.NET-провайдера построен поверх этого.

Когда вы, как разработчик фреймворка, возьмете зависимость от CSL, пользователям будет сложнее использовать ваше приложение. Пользователи должны будут настроить контейнер IoC и подключить его к CSL. Однако платформа не может проверить конфигурацию, как это может быть сделано при использовании системы конфигурации.NET, которая поддерживает все виды проверки в ней.

Недавно я прочитал концепцию поиска сервисов. Это способ помочь уменьшить связь, но требует связывания кода с локатором - не контейнером, поддерживающим локатор, а сам локатор. Это компромисс, но может быть полезным в правильной ситуации.

Одна ситуация, в которой это может быть полезно, - это когда у вас есть код, который не использует DI, такой как устаревший код - я сейчас в этой лодке. Добавление необходимых объектов через SL, а не их непосредственное создание, позволяет добавить некоторую абстракцию. Я вижу это как промежуточный шаг между SL и DI/IoC.

Если у вас есть библиотечный код, который нуждается в службах, и этот код может быть размещен в контексте более крупной платформы / среды выполнения, тогда инфраструктура / среда выполнения должны предоставить механизм, с помощью которого можно запускать некоторый пользовательский код при запуске, в котором вы можете инициализировать ваш контейнер и зарегистрируйте зависимости. Хорошим примером того, где CSL может быть проблематичным, является использование его в контексте MSCRM. Вы можете настроить собственную бизнес-логику, зарегистрировав плагины, которые MSCRM-среда выполняет для определенных событий. Проблема, с которой вы сталкиваетесь, заключается в том, где вы запускаете логику регистрации, поскольку нет события "запуска", на которое вы можете подписаться для настройки вашего DI-контейнера. Даже если бы вы могли как-то настроить свой DI, вам нужно было бы поместить библиотеки CSL и DI в GAC, поскольку это единственный способ вызвать сторонний код из плагина (еще один элемент, который нужно добавить в контрольный список развертывания). В таких сценариях вам лучше иметь свои зависимости в качестве параметров конструктора, которые вызывающий код может инициализировать по своему усмотрению (либо путем внедрения конструктора, либо вручную "обновляя" соответствующую реализацию интерфейса).