Using Dependency Injection for Hardware Abstraction

I am playing around with Dependency Injection in relation to hardware abstraction. So basically I have some hardware devices that I want to control from a C # application. These devices usually have a root device that is used to access leaf devices. The structure is pretty simple: LeafDevice1 and 2 are linked via interface1 to RootDevice1, LeafDevice3 is linked to RootDevice2, etc.

Now I thought I could solve this problem with dependency injection, since leaf devices usually don't care how they are connected as long as they are connected to the specified interface. But I'm wondering if dependency injection using an IOC container is really the best way to do this. The main reason for my doubts: I use named dependencies ALL THE TIME. If I connect devices B and C to root device A, I want to make sure they refer to the same device. Also, I use a lot of singleton scopes as the named dependency xyz only needs to exist once.

So in my situation, setting up a container means glueing a lot of named dependencies together.

As I understand it, using IOC containers makes sense when you want to specify which implementation will be introduced. But as far as I can see I am using a container to control which specific object is used there. The actual implementation of the specified object may, of course, differ, but this is even more "what is used where?". not the question "which implementation is used".

Wouldn't it be better to build something like a device tree that 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 will depend on an abstract IBusInterface to communicate with real hardware devices. Root Device offers several BusMasters that can be used to communicate with specified leaf devices.

Thank you in advance

+3


source to share


1 answer


In my experience, it's worth using a DI container just to instantiate with a single window if you're using a singleton and / or lightweight drawing in your application.

Don't reinvent the wheel and don't repeat yourself at the same time.



The only consideration is performance. If using a DI container is as spec / expected then use it! They are well tested, much more professional and stable that you can write from scratch.

+1


source







All Articles