Search code examples
c#dependency-injectioninversion-of-controldecoratorsimple-injector

IoC registration for wrapper class


I have interface IA and implementations A:IA and B:IA. The B implementation has a dependency on IA with constructor DI so that B.ctor(IA).

The intent of this design is to wrap A with B and allow them to be used interchangeably. A is an adapter to a database, and B allows caching of that data.

IA is also depending on by provider classes in this system, so that when I register those providers I would like to use an instance of B. My object graph should basically look as follows:

new Provider(
    new B(
        new A(
            new DbContex("constr")
        )
    )
)

I have considered using a tagging interface such that IB:IA and B:IB, but then I would need to depend on IB on my providers instead of IA which would not be ideal.

I have also considered using a factory for IA that creates an instance of B using an instance of A, but that feels wrong.

So I guess I am looking for some way of accomplishing this registration using the simpleinjector IoC container.

Example code

public class A : IA
{
    private readonly DbContext _context;

    public A(DbContext context)
    {
        _context = context;
    }

    public T Get<T>()
    {
        // Do stuff to get and
        // return value from database.
    }

    public void Set<T>(T value)
    {
        // Do stuff to set value
        // in database.
    }
}

Wrapper class:

public class B : IA
{
    private readonly IA _adapter;

    public B(IA adapter)
    {
        _adapter = adapter;
    }

    public T Get<T>()
    {
        // Do stuff to get and
        // return value from cache
        // or database adapter.
    }

    public void Set<T>(T value)
    {
        // Do stuff to set value
        // in cache and database.
    }
}

Consumer of IA:

public class Provider
{
    private readonly IA _adapter;

    public Provider(IA adapter)
    {
        _adapter = adapter;
    }
}

Solution

  • What you're looking for is known as the decorator pattern.

    Simple Injector has excellent support for applying decorators, probably the best support compared to other mainstream IoC containers.

    You can read all about the decorator subsystem here: Aspect-Oriented Programming in the documentation.

    For this basic case the registrations needed are straightforward:

    container.Register<IA, A>();
    container.RegisterDecorator<IA, B>();
    

    And don't forget to put 'IA' in the ctor of B.