Как я уже упоминал в своем комментарии к ответу Стивена, ваш вопрос, похоже, основан на неправильном понимании цели фабричного паттерна и полиморфизма. Я оставлю это его ответу, но давайте вернемся к вашему неправильному пониманию внедрения зависимости ...
1) Внедрение зависимостей предназначено для служб, а не для организаций
Не ясно, каковы ваши компоненты и дерево, но я предполагаю, что они являются объектами в вашем домене, а не службами, которые обрабатывают их. Внедрение зависимостей предназначено для внедрения услуг (в самом общем смысле) в другие службы или слои клея. Примеры включают внедрение репозитория в контроллер MVC или размещение веб-службы в Твиттере в модели представления или фабрику продуктов в службу манипулирования продуктами.
2) Внедрение зависимостей и их каркасы не имеют ничего общего с заводским шаблоном
Хотя он называется AutoFac , он не является своего рода auto matic fac тори-генератором, так как Unity - это способ объединить все ваши занятия в одном или Виндзорский замок это ... ну ... я понятия не имею. Единственное соединение, которое могут иметь эти две концепции, - это если фабрика является одной из вышеупомянутых служб, которые вы внедряете.
3) Внедрение зависимостей зависит от хорошего дизайна
То есть вы должны использовать надлежащие объектно-ориентированные соображения, например, использовать конструктор для построения класса. Хотя я подозреваю, что компоненты в вашем дереве являются сущностями (как обсуждалось выше), если бы они были сервисами, то метод Add
противоречил бы этим принципам проектирования: если классу нужен экземпляр MyBase
, он должен принять это как параметр конструктора с соответствующим условным выражением для выброса исключения, если этот инвариант не выполняется. Точно так же, SomethingElse
, очевидно, нужно дерево компонентов, которое может быть задано корневым узлом: ну, тогда он должен принять этот корневой узел в качестве параметра конструктора.
Другими словами, дружественная к внедрению зависимостей версия древовидной ситуации в конечном итоге выглядела бы как
interface INotificationService { }
class TwitterNotificationService : INotificationService { }
class FacebookNotificationService : INotificationService { }
class CompositeNotificationService : INotificationService
{
public CompositeNotificationService(IEnumerable<NotificationService> services) { }
// implement composite pattern
}
class NotificationController : Controller
{
public NotificationController(INotificationService service)
{
if (service === null)
{
throw new ArgumentNullException("service");
}
// ...
}
}
Позже, если бы вы использовали DI бедняка, вы бы сделали что-то вроде
var controller = new NotificationController(
new CompositeNotificationService(new []
{
new TwitterNotificationService(),
new FacebookNotificationService()
}));
Цель DI-фреймворка состоит в том, чтобы просто переместить код конструкции шаблона, подобный этому, в одно центральное место в вашем приложении ( составной корень ), эффективно удаляя конструкцию службы как проблему из вашего приложения и превращая это в детали конфигурации. Но ваше приложение должно быть совместимо с DI, что на самом деле просто означает соответствие базовым принципам ОО, таким как использование конструкторов, для работы DI.