How can I implement ILogger
dependency injection (like a hosted app) in a non-hosted Console app? In the code below, I'd like to work like logTest1
. Is that possible?
Below is my appsettings.json - I would prefer to not have to define every class, but this doesn't work anyway.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"ClientTestCli.LogTest": "Trace"
}
}
My Console app Program:
class Program
{
static void Main(string[] args)
{
HandleArgs(args);
var serviceProvider = ContainerConfiguration.Configure();
var logTest1 = new LogTest();
var logTest2 = new LogTest(serviceProvider.GetService<ILogger<LogTest>>());
logTest1.LogStuff();
logTest2.LogStuff();
}
}
Container configuration:
internal static class ContainerConfiguration
{
public static ServiceProvider Configure()
{
return new ServiceCollection()
.AddLogging(l => l.AddConsole())
.Configure<LoggerFilterOptions>(c => c.MinLevel = LogLevel.Trace)
.BuildServiceProvider();
}
}
A test class:
internal class LogTest
{
ILogger<LogTest> logger;
public LogTest(ILogger<LogTest> logger = null)
{
this.logger = logger;
}
public void LogStuff()
{
logger?.LogCritical("This is a critical log");
}
}
Add LogTest
to the service collection and resolve it using the provider and the provider will inject the configured loggers
Refactor your composition root
internal static class ContainerConfiguration {
public static IServiceProvider Configure(Action<IServiceCollection> configuration = null) {
var services = new ServiceCollection()
.AddLogging(logging => {
logging.ClearProviders();
logging.AddConsole();
})
.Configure<LoggerFilterOptions>(c => c.MinLevel = LogLevel.Trace);
configuration?.Invoke(services);
return services.BuildServiceProvider();
}
}
And use that at start up
static void Main(string[] args) {
HandleArgs(args);
IServiceProvider serviceProvider = ContainerConfiguration.Configure(services => {
services.AddTransient<LogTest>();
});
LogTest logTest = serviceProvider.GetService<LogTest>();
logTest.LogStuff();
}
If the provider is used, it will take care of building object graph, which includes injecting required dependencies.
.Net Fiddle of a working example.