У нашего клиента огромная устаревшая система, которая находится в процессе обновления с .NET 1.1 до .NET 4.0.Наряду с этим будет портирование базовых платформ на WCSF 2010 для веб-приложений и Enterprise Library 5.0 ou1 в качестве базовой корпоративной инфраструктуры.Наряду с этими платформами предоставляются средства DI.
WCSF эффективно заставляет MVP и проекты модулей полагаться на ObjectBuilder и его атрибуты, поэтому обновления веб-приложений следуют этому шаблону.
Веб-приложения потребляютдополнительные сервисы приложений на уровне приложений (через WCF).С тех пор как базовая структура стала Enterprise Library, блок приложения Unity «скользил бесплатно».Но существующий стиль кодирования остается унаследованным, поэтому он не имеет принципиального перехода на DI в отличие от веб-слоя.
Типичные уровни на уровне приложения:
- Бизнес-фасад (BF)- предоставляет общедоступные грубые бизнес-функции, контролирует транзакции.
- Бизнес-компоненты (BC) - компоненты гранулярной логики, координируемые методами фасада для выполнения фактической работы в транзакции.
- Доступ к данным (DA)) - чтение / запись данных для бизнес-компонентов
Почему я упомянул выше, стиль остается устаревшим, потому что служебное взаимодействие между уровнями происходит путем передачи DataSets (и они огромны)по сети.Эти DataSets передаются в конструктор каждого объекта.Например, код psuedo
BF.SomeExposedMethod(StrongTypeDS ds)
{
this.BeginTransaction();
BizComp bc = new BizComp(ds);
bc.ShareTransaction();
bc.DoWork();
this.CommitTransaction();
}
BC.DoWork()
{
DataAccess da = new DataAccess(this.transaction, this.ds);
// perform work
da.SaveWork(this.ds);
}
Более того, конструкторы этих классов основаны на стиле их родительских абстрактных классов;они ожидают получения DataSets при создании экземпляра.
Я читал DI Марка Симана в .NET и другие публичные интернет-источники о проблемах DI.Из всего этого я, кажется, понимаю, что DI выглядит хорошо для подготовки графика чистых объектов , готовых к работе.Под чистым я подразумеваю пустые контекстные данные.Эти шаблоны устаревшего кода имеют своих конструкторов, ожидающих рабочие данные и контекст с самого начала.
Если я правильно понимаю принцип корня композиции, необходимо перестроить конструкторы и методы, чтобы передать контекстные наборы данныхв через свойства.Мне непонятно, как DI-контейнер (в данном случае Unity) может сам по себе определить, в какой DataSet вставлять. Наверняка это не может быть пустой совершенно новый DataSet.На этой стадии разработки (которую я не принимаю непосредственного участия в проекте, но поддерживаю со стороны), я не смогу рекомендовать фундаментальное изменение в реализации WCF, чтобы сделать его корнем композиции до создания экземпляра объекта фасада.
Кроме того, я не получил значительных советов о том, как DI применяется для создания экземпляров объектов на основе условий времени выполнения ?На основе состояния выполнения данных могут быть созданы дополнительные объекты, а тип может отличаться в зависимости от категории данных.Казалось бы, самым простым способом введения некоторого уровня практики DIP и DI в это приложение было бы использование контейнера Unity в качестве локатора служб;захватывать экземпляр только в тот момент выполнения при необходимости.
ОБНОВЛЕНИЕ ОТВЕТА
Основываясь на совете Марка Симана, я изготовил следующий POC
BF с контейнером Unity.Хотя я успешно экспериментировал с пакетом Unity.Wcf, я также сделал следующую ближайшую вещь с каждым BF-корнем Composition, где каждый метод фасада будет вызывать контейнер для разрешения графа объектов, необходимых для выполнения работы метода.(Это более реалистичный шаблон, который эта среда может подобрать в данной ситуации.)
static ExampleBF()
{
container = new UnityContainer().LoadConfiguration();
}
BF получает разрешенный IBCFactory, который будет создавать конкретный BC с передаваемыми в реальном времени данными контекста.
DataSet IExampleService.GetProducts(DataSet ds)
{
IExampleBC bc = container.Resolve<IBCFactory>().CreateBC(ds);
// GetProducts() takes no parameter because DataSet already passed in on construction.
return bc.GetProducts();
}
BCFactory получает IDACFactory посредством инжектора конструктора.Который он вручает каждому экземпляру до нашей эры.
public BCFactory(IDACFactory DACFactory)
{
this.DACFactory = DACFactory;
}
IExampleBC IBCFactory.CreateBC(DataSet ds)
{
return new ExampleBC(this.DACFactory, ds);
}
BC будет полагаться на IDACFactory для предоставления ему ЦАП.
DataSet IExampleBC.GetProducts()
{
IExampleDAC dac = this.dacFactory.CreateDAC(this.ds);
return dac.GetProducts();
}
DACFactory аналогичным образом создает ЦАП на основе данных контекста.
IExampleDAC IDACFactory.CreateDAC(DataSet ds)
{
return new OrderDAC(ds);
}
Конечно,реальность ситуации со сложностью кодовой базы намного больше по величине, но, надо надеяться, этого простого примера будет достаточно для демонстрации им концепции DI.