c# - Simple Injector decoration with additional dependency -
i have decorator somethingloggerdecorator
supposed decorate isomething
instances 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 else " + withthis); this.decoratee.dosomethingelse(withthis); } }
how can use simple injector decorate instances of isomething
somethingloggerdecorator
, inject instance of ilogger
into each of decorators using static factory method logmanager.getlogger(decoratee.gettype())
decoratee actual instance decorated? lifetime of injected ilogger
somethingloggerdecorator
should match lifetime of decoratee.
there multiple ways in simple injector.
first of all, can let decorator's constructor depend on decoratorcontext class. decoratorcontext
contains contextual information decorator. contains information such types of wrapped decorators , type of actual implementation decorated (the real instance). decorator might follows:
public class somethingloggerdecorator : isomething { private readonly isomething decoratee; private readonly decoratorcontext context; public somethingloggerdecorator(isomething decoratee, decoratorcontext context) { this.decoratee = decoratee; this.context = context; } public void dosomething() { var logger = logmanager.getlogger(this.context.implementationtype); logger.info("doing something"); this.decoratee.dosomething(); } }
downside of use of decoratorcontext
class decorator needs take dependency on simple injector, means have move decorator inside composition root prevent application taking dependency on di library. can find more information use of decoratorcontext
class here.
another option make decorator generic , supply decorator type factory 1 of registerdecorator
overload can make correct decorator. instance:
public class somethingloggerdecorator<timplementation> : isomething { private readonly isomething decoratee; public somethingloggerdecorator(isomething decoratee) { this.decoratee = decoratee; } public void dosomething() { var logger = logmanager.getlogger(typeof(timplementation)); logger.info("doing something"); this.decoratee.dosomething(); } }
or optionally:
public class somethingloggerdecorator<timplementation> : isomething { private readonly isomething decoratee; private readonly ilogger<timplementation> logger; public somethingloggerdecorator(isomething decoratee, ilogger<timplementation> logger) { this.decoratee = decoratee; this.logger = logger; } public void dosomething() { this.logger.info("doing something"); this.decoratee.dosomething(); } }
with both implementations, can register decorator follows:
container.registerdecorator(typeof(isomething), c => typeof(somethingloggerdecorator<>).makegenerictype(c.implementationtype), lifestyle.transient, predicate: c => true);
with second implementation, move problem bit generic ilogger<t>
abstraction, implementation follows:
public class log4netadapter<t> : ilogger<t> { public void log(logentry entry) { var logger = logmanager.getlogger(typeof(t)); // todo: log } }
Comments
Post a Comment