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;
}
}
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.