I\'ve configured my console application\'s Main
like so
var services = new ServiceCollection()
.AddLogging(logging => logging.Add
The approach I used when trying to use an ILogger
(Because it's no longer injected), as to inject a ILoggerFactory
, and then when your code wants a specific logger (say its some custom factory you're new
ing up, LoggerFactory.CreateLogger("Logger Name")
- Below
But for your case,it looks like you want a ILogger<MyClass>
public class MyClass
{
private readonly ILoggerFactory _loggerFactory;
public MyClass(ILoggerFactory loggerFactory)
{
_loggerFactory = _loggerFactory;
}
public void MyFunc()
{
new MyNewThatsASpecialCase(_loggerFactory.CreateLogger("MyNewThatsASpecialCase"));
}
}
ILogger
is no longer registered by default but ILogger<T>
is. If you still want to use ILogger you can registered it manually with the following (Startup.cs):
public void ConfigureServices(IServiceCollection services)
{
var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetService<ILogger<AnyClass>>();
services.AddSingleton(typeof(ILogger), logger);
...
}
Where AnyClass can be something generic, such as:
public class ApplicationLogs
{
}
So:
public void ConfigureServices(IServiceCollection services)
{
var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetService<ILogger<ApplicationLog>>();
services.AddSingleton(typeof(ILogger), logger);
...
}
ILogger will now resolve via constructor injection
I am assuming you are using the default template for .net core web application.
In your your Startup.cs you should have a method like this↓↓↓↓↓↓↓
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//Do the service register here and extra stuff you want
services.AddLogging(config =>
{
config.AddDebug();
config.AddConsole();
//etc
});
}
Edit: I have written a simple program for you to show how it works
public class MyClass
{
private readonly ILogger<MyClass> _logger;
public MyClass(ILogger<MyClass> logger)
{
_logger = logger;
}
public void MyFunc()
{
_logger.Log(LogLevel.Error, "My Message");
}
}
public class Program
{
public static void Main(string[] args)
{
var services = new ServiceCollection().AddLogging(logging => logging.AddConsole());
services.AddSingleton<MyClass>();//Singleton or transient?!
var s = services.BuildServiceProvider();
var myclass = s.GetService<MyClass>();
}
}
Edit: Output of the program:
As noted in a comment, the accepted answer has the problem that BuildServiceProvider
should not be used in ConfigureServices
, since it creates another copy of each singleton (in fact, of the whole DI container). Here is an alternative one-liner that avoids that problem. In ConfigureServices
, add the line
services.AddSingleton<Microsoft.Extensions.Logging.ILogger>(provider =>
provider.GetRequiredService<Microsoft.Extensions.Logging.ILogger<AnyClass>>());
where AnyClass
can be any class, as explained in the accepted answer. This redirects the resolution of ILogger
to that of ILogger<AnyClass>
.
Like the accepted answer, this one has the disadvantage that Serilog's SourceContext
will be set to AnyClass
. So, if your Serilog configuration contains an outputTemplate
that contains {SourceContext}
, your log will show AnyClass
instead of the class that contains the logging statement.
Based on @Barry answer above found out how to register generic log provider for Microsoft.Extensions.DependencyInjection
:
var services = new ServiceCollection()
.AddLogging(logging => logging.AddConsole())
.BuildServiceProvider();
services.AddSingleton<ILoggerFactory, LoggerFactory>()
services.Add(ServiceDescriptor.Describe(typeof(ILogger<>),typeof(Logger<>),ServiceLifetime.Scoped))
In .NET Core, ILogger<T>
is automatically registered for you. As ILogger<T>
inherits from ILogger
, you can request an instance of ILogger<T>
from the IServiceProvider
.
For example:
services.AddSingleton<ILogger>(svc => svc.GetRequiredService<ILogger<MyClassType>>());
Note that this will return an ILogger<MyClassType>
wherever you've got a non-generic ILogger
constructor parameter so if you need more than one, look into creating it specifically for that instance by using the AddSingleton
(or transient/or scoped) implementationFactory override.