So, let's say I have an interface IThingFactory
:
public interface IThingFactory
{
Thing GetThing(int thingId);
}
Now, let's say I have a concrete implementation that retrieves Thing
s from a database. Now, let's also say I have a concrete implementation that wraps an existing IThingFactory
and checks for a Thing
's presence in, say, an in-memory cache before hitting the wrapped IThingFactory
. Something like:
public class CachedThingFactory : IThingFactory
{
private IThingFactory _wrapped;
private Dictionary<int, Thing> _cachedThings;
public CachedThingFactory(IThingFactory wrapped)
{
this._wrapped = wrapped;
_cachedThings = new Dictionary<int,Thing>();
}
public Thing GetThing(int thingId)
{
Thing x;
if(_cachedThings.TryGetValue(thingId, out x))
return x;
x = _wrapped.GetThing(thingId);
_cachedThings[thingId] = x;
return x;
}
}
How would I deal with a scenario like this using dependency injection with something like, say, Ninject, so that I could configure the DI container so that I can inject or remove a caching proxy like this, or, say, something that does logging, or (insert here)?
You can do something along the lines of:
Bind<IThingFactory> ().To<DefaultThingFactory> ().WhenInjectedInto<CachedThingFactory> ();
Bind<IThingFactory> ().To<CachedThingFactory> ();
This will let consumers not need to specify a name attribute, and is still relatively easy to further enhance. If you later wanted to add an additional "decorator" layer for logging, you could do:
Bind<IThingFactory> ().To<DefaultThingFactory> ().WhenInjectedInto<LoggingThingFactory> ();
Bind<IThingFactory> ().To<LoggingThingFactory> ().WhenInjectedInto<CachedThingFactory> ();
Bind<IThingFactory> ().To<CachedThingFactory> ();
Not the prettiest, but it works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With