Использование 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-контейнера соответствует спецификации / ожиданиям производительности, используйте его! Они хорошо проверены, гораздо более профессиональны и стабильны, что вы могли бы написать с нуля.

Другие вопросы по тегам