I have a decorator SomethingLoggerDecorator
that is supposed to decorate ISomething
instances with logging:
public class SomethingLoggerDecorator : ISomething
{
private readonly ISomething decoratee;
private readonly ILogger logger;
public SomethingLoggerDecorator(ISomething decoratee, ILogger logger)
{
this.decoratee = decoratee;
this.logger = logger;
}
public void DoSomething()
{
this.logger.Info("Doing Something");
this.decoratee.DoSomething();
}
public void DoSomethingElse(string withThis)
{
this.logger.Info("Doing Something Else with " + withThis);
this.decoratee.DoSomethingElse(withThis);
}
}
How can I use Simple Injector to decorate instances of ISomething
with SomethingLoggerDecorator
and inject an instance of ILogger
into each of those decorators using the static factory method LogManager.GetLogger(decoratee.GetType())
where decoratee is the actual instance that is to be decorated? Also the lifetime of the injected ILogger
as well as the SomethingLoggerDecorator
should always match the lifetime of the decoratee.
There are multiple ways to do this in Simple Injector.
First of all, you can let your decorator's constructor depend on the DecoratorContext class. The
DecoratorContext
contains contextual information about the decorator. It contains information such as the types of the wrapped decorators and the type of the actual implementation that is decorated (the real instance). So your decorator might look as follows:Downside of the use of this
DecoratorContext
class is that your decorator needs to take a dependency on Simple Injector, which basically means you will have to move the decorator inside your Composition Root to prevent your application from taking a dependency on the DI library. You can find more information about the use of thisDecoratorContext
class here.Another option is to make your decorator generic and supply a decorator type factory to one of the
RegisterDecorator
overload that can make the correct decorator. For instance:Or optionally:
With both implementations, you can register the decorator as follows:
With the second implementation, you will move the problem a bit to the generic
ILogger<T>
abstraction, but an implementation could look as follows: