Using Dependency Injection for hardware abstraction

232 Views Asked by At

I've been playing around with Dependency Injection in connection with hardware abstraction. So, basically I have some hardware devices which i want to control from within a C# application. These devices have usually a root device which is used to access leaf devices. The structure is quite simple: LeafDevice1 & 2 are connected through Interface1 to RootDevice1, LeafDevice3 is connected to RootDevice2 and so forth.

Now i thought i can solve this issue with dependency injection since "leaf" devices usually don't care how they're connected as long as they're connected to a specified interface. But I'm wondering if Dependency Injection using an IOC container is actually the best way to do it. The main reason for my doubts is: I use named dependencies ALL THE TIME. If I connect device B and C to root device A I want to make sure that they're referring to the exact same device. Also, I use a lot of singleton scopes since a named dependency xyz should only exist once.

So in my situation configuring the container means gluing together a lot of named dependencies.

As I understand it, using IOC containers makes most sense when you want to specify which implementation will be injected. But as far as I can see, I'm using the container to manage which specific object is used where. The actual implementation of said object can, of course, be different, but it's still more of a "what is used where?" not a "which implementation is used" question.

Wouldn't it be better to build something like a device tree which i can use to access my devices?

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");

In this example LeafDevices would depend on an abstract IBusInterface to communicate with the actual hardware devices. Root Device offers several BusMasters which can be used to communicate with said leaf devices.

Thanks in advance

1

There are 1 best solutions below

0
On BEST ANSWER

By my experience it worth to use a DI container just for its singleton scoped instance creation, in case you are using singleton and/or lightweight pattern heavily in your application.

Do not reinvent the wheel, and do not repeat yourself both satisfied then.

The only consideration would be the performance. If using a DI container fits to the performance specification / expectation then use it! They are well tested, much more professional and stable what you could write from scratch.