We use Simple Injector in ASP.NET Core application. Recently we've decided to use Serilog for logging purposes.
Configuration was done in Program.cs as stated in their documentation. Then, in order to make Simple Injector able to resolve ILoggerFactory
I did something like this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
// As per my understanding, we force SimpleInjector to use
// ILoggerFactory registration from IApplicationBuilder
container.CrossWire<ILoggerFactory>(app)
}
After that ILoggerFactory
can be injected wherever we use it. And it works fine (creates new instances ILogger<T>
).
But this is annoying, to create instance from factory every time we need.
It would be better to get ILogger<T>
directly in dependent class, instead of ILoggerFactory
.
So, how can I register ILogger<T>
to get instance in case like below?
public class HelloWorldController : Controller
{
public HelloWorldController(ILogger<HelloWorldController> logger)
{
// ...
}
}
Although Alsami's answer would work, use the following registration instead:
container.RegisterConditional(
typeof(ILogger),
c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
// This next call is not required if you are already calling AutoCrossWireAspNetComponents
container.CrossWire<ILoggerFactory>(app);
This exact example is shown in the documentation.
This registration allows injecting the Logger<T>
into a non-generic ILogger
constructor argument, where the T
of Logger<T>
becomes the type the logger is injected into. In other words, when HelloWorldController
depends on ILogger
, it will get injected with a Logger<HelloWorldController>
. This means you can simplify your HelloWorldController
to the following:
public class HelloWorldController : Controller
{
public HelloWorldController(ILogger logger)
{
// ...
}
}
By letting your application components depend on ILogger
rather than ILogger<T>
you:
- Simplify your application code
- Simplify your unit tests
- Remove the possibility of making accidental errors, because it becomes impossible to inject the wrong logger.
You also have to register the logger iteself as a generic type.
I don't know simple injector but this should be the correct syntax.
container.Register(typeof(ILogger<>), typeof(Logger<>), Lifestyle.Singleton);