Why does .NET Core DI container not inject ILogger?
In order for MS.DI to be able to do a mapping from
ILogger<T> where the
T becomes the consumer, it must support context-based injection. This means that when building an application using MS.DI, you will have to let your classes depend on
There are multiple reasons why MS.DI lacks this feature. I think the two most important reasons are:
- MS.DI only implements features that are required for framework components itself. Remember: MS.DI was built and designed especially for the ASP.NET Core framework, its components, and its third-parties. Much less to be a fully fledged DI Container
- MS.DI tries to be a lowest common denominator (LCD) where it tries to only support features that all other DI Containers support as well to allow you to replace this built-in container with a more mature, feature-rich DI Container.
I understand your annoyance. It would be great to see MS.DI support context-based injection, because it makes a lot of sense to depend on
ILogger instead for your application components, because this makes your code simpler, easier to test, and less error prone.
Unfortunately, because of MS.DI's design and its LCD philosophy, it's unlikely that it ever gets such feature. Every time Microsoft adds behavior, a long and complex discussion is started with maintainers of most DI Containers to see how such feature can be supported in a way that is compatible with all other libraries (I've been parted of many of these discussions myself). This is a daunting task, and already proved to be impossible in some cases.
Instead, it makes sense to select a more mature and feature-rich DI Container that contains such feature, and many other features. For Simple Injector, for instance, we added integration for injecting
ILogger. But there are other DI Containers that allow you to inject
The dependency injection system doesn't register
ILogger. Instead it registers
ILogger<T>. If you need an instance of a logger, you will need to accept
The reason behind this is that the generic argument is used to build the logger's category name--something which all loggers require. With a non-generic logger there's not necessarily a good default name. If you really want a non-generic
ILogger, you can register one like this (change the name as you please):
services.AddSingleton(sp => sp.GetRequiredService<ILoggerFactory>().CreateLogger("DefaultLogger"));
Alternatively, you can accept an
ILoggerFactory in your constructor and then create your own logger on the fly.