#c_sharp #net #dependency_injection
Взялся я за реализацию IoC для сервиса данных. Сделал вот так:
interface IDataService
{
}
и его реализация (возьмем для примера RpcJson):
class JsonRpcDataService : IDataService
{
}
Далее регистрируем их в IoC-контейнере. Тут все пока понятно.
Далее переходим к собственно к реализации. Я определил следующую структуру сервиса
данных:
Модели - тут все понятно
Коллекторы - это вспомогательные классы для получения данных
Обработчики - вспомогательные классы для обработки данных (сохранения, например)
Опишем интерфейс модели:
interface IBook
{
string Autor { get; set; }
...
}
Коллектор:
interface IBooksCollector
{
IEnumerable GetItems();
...
}
И обработчик:
interface IBooksHandler
{
void Save(IBook book);
...
}
Ну и, соответственно, для реализуем каждый из них для JsonRpc. Далее дополняем интерфейс
IDataService:
interface IDataService
{
IBook CreateBook();
IBooksCollector CreateBooksCollector();
IBooksHandler CreateBooksHandler();
}
И реализуем эти методы в JsonRpcDataService. Их я сделал для того, чтобы я на уровне
ViewModel должен был бы связывать только IDataService с RpcJsonDataService, а не все
интерфейсы с их реализациями. Чтобы в итоге я мог делать как-то так:
var dataService = IoC.Resolve();
// Создаем модель
IBook book = dataService.CreateBook();
Вместо
IBook book = IoC.Resolve();
и где-то до этого связывание
IBook book = IoC.Register();
где Book - реализация IBook для RpcJson. Так как моделей может быть очень много,
то вместо кучи строк вида:
IoC.Register();
Все сводится к одной:
IoC.Register();
По ходу у меня появились вопросы, на которые я и прошу Вас ответить:
Правилен ли такой подход с созданием инстансов? Или может сделать фабрики вида CreateModel(),
в которую в качестве параметра T будет передаваться интерфейс, а фабрика уже будет
решать что "отдать"?
Стоит ли вообще делать интерфейсы для моделей, или лучше описать их сразу? Выделил
я их для того, чтобы не загромождать из атрибутами вида [JsonProperty(...)], необходимые
для сериализации, ведь эти атрибуты нужны только для сервера RpcJson
Ответы
Ответ 1
В первую очередь - неверно ваше желание обойтись минимальным количеством регистраций компонентов. Если у вас 40 компонентов нет ничего зазорного в том чтобы регистрировать все 40 компонентов в контейнере. Это не будет ошибкой. Более того, хотя многие контейнеры и поддерживают в том или ином виде автоматическую регистрацию компонентов, Castle Windsor например, насколько мне известно, обязывает вас явно регистрировать каждый компонент, и такой подход с явной регистрацией имеет определенный смысл. Но здесь вы вправе выбрать то что вам ближе - автоматическая регистрация или явная регистрация каждого компонента, оба подхода имеют свои преимущества и недостатки. Второе - вы ошибочно ассоциируете регистрацию компонента и последующее получение его из контейнера. Если вы написали IoC.Register(); это не означает что потом для получения IComponent вы обязаны получать его из контейнера. Как правило, вы регистрируете n - компонентов, но из IoC контейнера - запрашиваете только один. Например, если у вас ASP-MVC приложение, в нем может быть много компонентов (контроллеры, сервисы и т.д.), но запрос компонента из IoC контейнера у вас будет всего один - это будет запрос контроллера в фабрике контроллеров. Чтобы понять зачем регистрировать 10 компонентов, если запрашиваться будет только 1 читайте про основные паттерны внедрения зависимостей - внедрение конструктора и внедрение свойства. Ответы на ваши вопросы: Использование фабрик для создания моделей - нормальный подход. Создавать фабричный метод вида CreateModel () где T интерфейс модели, не имеет смысла. Подумайте, чем этот метод будет принципиально отличаться от аналогичного метода IoC-контейнера? Скорее всего не стоит делать интерфейсы для моделей. Использование IoC контейнера вовсе не обязывает вас делать интерфейсы для каждого класса в вашем приложении. Для моделей интерфейсы чаще всего не нужны. По формулировке вашего вопроса видно что вы довольно плохо ориентируетесь в теме и двигаетесь в неверном направлении. Вам стоит потратить немного времени на ее изучение, прежде чем проектировать приложение. В частности паттерны внедрения зависимостей, упомянутые выше (внедрение конструктора и внедрение свойства), существенно важнее для понимания DI, чем любые вопросы, связанные с регистрацией компонентов в IoC-контейнере. Вообще внедрение зависимостей это как раз про эти паттерны, а IoC-контейнер это просто инструмент, облегчающий построение приложения с использованием DI, и DI можно применять вообще без IoC-контейнера. В комменатриях @cybrex посоветовал прочитать книгу Симан М. - Внедрение зависимостей в .NET. Я присоденияюсь к этому совету, почитайте - не пожалеете.
Комментариев нет:
Отправить комментарий