Unable to resolve ILogger from Microsoft.Extensions.Logging

前端 未结 7 1043
太阳男子
太阳男子 2021-02-02 04:56

I\'ve configured my console application\'s Main like so

var services = new ServiceCollection()
                .AddLogging(logging => logging.Add         


        
相关标签:
7条回答
  • 2021-02-02 05:28

    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 newing 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"));
        }
    }
    
    0 讨论(0)
  • 2021-02-02 05:29

    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

    0 讨论(0)
  • 2021-02-02 05:31

    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:

    0 讨论(0)
  • 2021-02-02 05:37

    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.

    0 讨论(0)
  • 2021-02-02 05:42

    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))
    
    0 讨论(0)
  • 2021-02-02 05:43

    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.

    0 讨论(0)
提交回复
热议问题