1

A very common logging goal I find in various projects, is that any class/object which creates a log entry will record its own class/object name into that entry. If the log entry is for an exception and stack-trace, that information is included for free. But if the log entry is not for an exception, then a variety of other approaches are typically used to obtain this result:

  1. Hard-code a const field into each class, which holds the name of the class (or the logger itself!). The logger is given that const when logging.
  2. The logger is wrapped with code that reflects the call stack, to determine which class had made the logging invocation. The name is then added to the log entry.
  3. Each class is injected with a logger instance which already knows the name of the class in which it is injected.

A simple example of #3 looks like this:

ILogger logger = new MyLogger("AmazingClass");
IAmazingClass foo = new AmazingClass(logger);

What I would like to know is if any IOC container, particularly Unity, is capable of helping to solve this "scenario #3" elegantly? If yes, how?

I feel the answer should be simple: the IOC container "knows" which class it is about to construct and inject, and offers that "dependor" information to the "dependee" before it finishes resolving the type.

For example, perhaps Unity could accomplish this through delegate registration and a "reverse reflection" registration like this:

var container = new UnityContainer();
container.RegisterType<ILogger, MyLogger>(new InjectionFactory(
    (Type targetOfInjection) => new MyLogger(targetOfInjection.Name)
);

I made up that syntax, but it is entirely believable. That said, what in reality does Unity (or another IOC container) offer for proposed capability?

p.s. I personally am "ok" with my logger and logging making no attempt to capture the class/object names for non-exception entries. Keeps the code simpler. But if I am forced to do this approach, I usually take the stack-reflection option (scenario #2). It would be interesting to know what other approaches people favor when they too are required to capture class names in non-exception logging statements. Ultimately, however, this question focuses on using an IOC container.

Steven
  • 166,672
  • 24
  • 332
  • 435
Brent Arias
  • 29,277
  • 40
  • 133
  • 234

1 Answers1

1

That said, what in reality does Unity (or another IOC container) offer for proposed capability?

I can't answer the question for Unity, but using Simple Injector, you can register this as follows:

container.RegisterWithContext<ILogger>(context =>
    new MyLogger(context.ImplementationType.Name));

You need to add the RegisterWithContext extension method using this code snippet from the Advanced Scenarios section in the Simple Injector documentation. Big plus is that with Simple Injector even this context based registration is resolved blazingly fast.

But please note that context based injection is typically a design smell. The fact that you see this pattern everywhere in the field, doesn't make it correct. So before you continue, please make sure that you're not logging too much and your application design follows the SOLID principles.

Community
  • 1
  • 1
Steven
  • 166,672
  • 24
  • 332
  • 435