Использование Dependency Injection для аппаратной абстракции
Я играл с Dependency Injection в связи с аппаратной абстракцией. Итак, в основном у меня есть несколько аппаратных устройств, которыми я хочу управлять из приложения C#. Эти устройства обычно имеют корневое устройство, которое используется для доступа к конечным устройствам. Структура довольно проста: LeafDevice1 & 2 подключены через Interface1 к RootDevice1, LeafDevice3 подключен к RootDevice2 и так далее.
Теперь я подумал, что смогу решить эту проблему с помощью внедрения зависимостей, поскольку "конечным" устройствам обычно не важно, как они подключены, если они подключены к указанному интерфейсу. Но мне интересно, является ли Dependency Injection с использованием контейнера IOC лучшим способом для этого. Основная причина моих сомнений заключается в следующем: я использую именованные зависимости ВСЕ ВРЕМЯ. Если я подключаю устройства B и C к корневому устройству, я хочу убедиться, что они ссылаются на одно и то же устройство. Кроме того, я использую много одноэлементных областей, поскольку именованная зависимость xyz должна существовать только один раз.
Поэтому в моей ситуации настройка контейнера означает склеивание множества именованных зависимостей.
Насколько я понимаю, использование контейнеров IOC наиболее целесообразно, когда вы хотите указать, какая реализация будет внедрена. Но, насколько я вижу, я использую контейнер для управления тем, какой конкретный объект и где используется. Реальная реализация указанного объекта может, конечно, отличаться, но все же это скорее "что используется где?" не вопрос "какая реализация используется".
Не лучше ли построить что-то вроде дерева устройств, которое я могу использовать для доступа к своим устройствам?
Bind<RootDevice>().ToConstructor<RootDevice>(e => new RootDevice(serialNumber))
.InSingletonScope().Named("ConcreteRootDevice");
Bind<IBusMaster>().ToMethod<IBusMaster>(e => e.Kernel.Get<RootDevice>("ConcreteRootDevice")
.GetBusMaster(0)).Named("ConcreteBus1");
Bind<IBusMaster>().ToMethod<IBusMaster>(e => e.Kernel.Get<RootDevice>("ConcreteRootDevice")
.GetBusMaster(1)).Named("ConcreteBus2");
Bind<IBusMaster>().ToMethod<IBusMaster>(e => e.Kernel.Get<RootDevice>("ConcreteRootDevice")
.GetBusMaster(2)).Named("ConcreteBus3");
Bind<IBusMaster>().ToMethod<IBusMaster>(e => e.Kernel.Get<RootDevice>("ConcreteRootDevice")
.GetBusMaster(3)).Named("ConcreteBus4");
Bind<LeafDevice>().ToConstructor<LeafDevice>(o =>
new LeafDevice(o.Context.Kernel.Get<IBusInterface>("ConcreteBus1")))
.Named("ConcreteLeafDevice1");
Bind<LeafDevice>().ToConstructor<LeafDevice>(o =>
new LeafDevice(o.Context.Kernel.Get<IBusInterface>("ConcreteBus1")))
.Named("ConcreteLeafDevice2");
Bind<LeafDevice>().ToConstructor<LeafDevice>(o =>
new LeafDevice(o.Context.Kernel.Get<IBusInterface>("ConcreteBus2")))
.Named("ConcreteLeafDevice3");
В этом примере LeafDevices будет зависеть от абстрактного интерфейса IBusInterface для связи с реальными аппаратными устройствами. Корневое устройство предлагает несколько BusMasters, которые можно использовать для связи с указанными конечными устройствами.
заранее спасибо
1 ответ
По моему опыту, стоит использовать DI-контейнер только для создания экземпляра в одной области действия, если вы используете в своем приложении одноэлементный и / или облегченный шаблон.
Не изобретайте велосипед и не повторяйте себя удовлетворенными тогда.
Единственным соображением будет производительность. Если использование DI-контейнера соответствует спецификации / ожиданиям производительности, используйте его! Они хорошо проверены, гораздо более профессиональны и стабильны, что вы могли бы написать с нуля.