Как понять правило: «Хранить в IoC контейнере только сервисы. Не хранить никаких сущностей». - PullRequest
3 голосов
/ 24 августа 2011

Правило «Хранить в IoC только контейнерные сервисы. Не хранить никаких сущностей». Я нашел в этом блоге , и у него много сторонников.

Есть также пример конструктора класса:

    MyClass(ILog log, 
            IAudit audit, 
            IPermissions permissions, 
            IApplicationSettings settings) {/*..*/}

где MyClass был объявлен как объект, который не должен храниться в контейнере.

Таким образом, «готовый сервис IoC» не может зависеть от инфраструктуры .. услуг.

Но теперь я совершенно не понимаю, как «люди IoC» работают с «реальным кодом». Служба в C # по-прежнему будет разрабатываться как класс, и этот класс обычно зависит от класса, который инкапсулирует ведение журнала, редко зависит от класса, который инкапсулирует пользовательскую обработку исключений (например, преобразование необработанного исключения в FaultContract) и т. Д. ...

Я вижу несколько способов: Может быть, они просто не объявляют эти зависимости инфраструктуры? Использовать их как функциональность, доступную из статических методов?

Или, может быть, «сторонники IoC» считают, что служба «IoC ready» должна публиковать события log / trace / authenticate / handleException как часть контракта на обслуживание (и тогда да - нет «зависимостей от инфраструктуры»)? Но это также означает, что такой сервис должен быть дуплексным (для публикации событий журнала) ...

Может быть, их "услуги" - это только прокси? Прокси не зависят от инфраструктуры, поскольку вся инфраструктура удаленная, но я не рад, что контейнер IoC следует использовать для хранения только прокси. Я прав в своем разочаровании? Но тогда как насчет MS Enterprise Library, которая предназначена для хранения логгеров и обработчиков в контейнере Unity?

APPEND:

Я так понимаю: есть сервисы (с контрактами), есть юридические лица (бизнес) и есть инфраструктурные вещи LogWriter, AuthenticationProvider; - создание / хостинг-сервис. Я инициирую его с помощью некоторых инфраструктурных вещей (поэтому я публикую зависимости от инфраструктуры, а не от субъектов). Что я до сих пор не понимаю, прав я в этом или нет?

ПРИЛОЖЕНИЕ 2:

После обсуждения я понимаю ситуацию таким образом. ILog и т. Д. - это сервисы (даже если они являются инфраструктурными сервисами), и поэтому, если «MyClass» является реализацией некоторого сервиса, правило не нарушается. Это означает, что правило хорошее, а образец плохой.

Осталась одна проблема: я все еще не понимаю противопоставление сущностей и услуг в одном предложении без объяснения причин. Они из разных концептуальных слоев: 1) сервис-сообщения; и 2) бизнес-правила-сущности. Поэтому, возможно, сначала я должен принять новую терминологию.

Ответы [ 3 ]

3 голосов
/ 24 августа 2011

Краткий ответ: субъекты не должны зависеть от услуг!Это огромная часть «инверсионной» части инверсии зависимостей.Как указано в сообщении, на которое вы ссылаетесь:

Я обнаружил, что дизайн примера вопроса неверен в том смысле, что сущность (которой является MyClass) НЕ должна иметь зависимости от инфраструктуры (или любой другой)Сервисы.

MyClass, в вашем примере, зависит от трех сквозных задач, плюс IApplicationSettings.Сквозные проблемы должны быть представлены с использованием методов AOP / динамического прокси или событий в стиле pubsub, если вы предпочитаете.И MyClass должен вводиться с настройками, специфичными для его функциональности, независимо от того, какая служба отвечает за его создание.Например, PersonFactory можно ввести с помощью IApplicationSettings, затем создать Person объекты, передав appSettings.SomePersonRelatedSetting в конструктор Person.

1 голос
/ 24 августа 2011

Правило «Хранить в IoC только контейнерные сервисы. Не хранить никаких сущностей».означает, что вы должны зарегистрироваться в паре контейнеров IoC interace - implementation.Это правило является результатом принципа инверсии зависимостей .Согласно вашему примеру это означает, что вы должны извлечь открытый интерфейс из вашего MyClass и использовать его вместо реализации MyClass.

0 голосов
/ 24 августа 2011

Правило, которое говорит, что

"Store in IoC container only services. Do not store any entities."

говорит с концептуальной точки зрения, а не с точки зрения реализации.Концептуально сущность представляет данные (или состояние) и, возможно, правила, связанные с данными (как методы).Сервис представляет функциональность, предоставляемую посредством опубликованного контракта, и, как правило, сервисы с полным состоянием не являются хорошей идеей.Таким образом, хотя конструкция C # class будет использоваться для представления как реализации сервиса, так и реализации сущности - это правило говорит о том, что в IoC должны быть включены только сервисы.IoC действительно действует как настраиваемая сверхгибкая фабрика, которая обеспечивает правильную реализацию сервиса для требуемого контракта на обслуживание.Опять же, может быть шаблон, такой как ActiveRecord, где, возможно, объединены функциональность данных и персистентности - мне как таковой не нравится шаблон, но есть много последователей, и типичное использование помещает такие объекты в контейнер IoC.Тем не менее, важным отличием будет, вероятно, то, что объект будет зарегистрирован по какому-либо контракту (а не по реализации)

Снова обратите внимание, что ваш код зависит от контрактов на обслуживание, а не от конкретной реализации сервиса.Теперь зависимости можно раскрыть и разрешить несколькими способами.Вы можете пометить зависимости, поместив их в качестве параметров конструктора ИЛИ как открытый метод получения / установки ИЛИ, используя декларативный синтаксис, такой как атрибуты.Они обычно разрешаются автоматически DI-фреймворком.Тем не менее, вы всегда можете получить / разрешить некоторые услуги, сделав явный вызов, такой как ILog log = DIContainer.Get<ILog>();.Итак, что касается инфраструктурных сервисов, я думаю, что автор блога говорит о том, что не маркируйте инфраструктурные сервисы как явные зависимости (по аргументам конструктора или свойствам и т. Д.).Вы можете разрешить их с помощью кода (как указано выше) или, возможно, с помощью простых одноэлементных помощников и т. Д. В некотором смысле он прав, потому что всегда можно предположить, что каждый сервис / класс зависит от инфраструктуры, и поэтому нет необходимости устанавливать зависимости с помощью общедоступного API.

...