如何将 appsettings.json 中的设置注入 ILoggerProvider?

How to inject settings from appsettings.json to an ILoggerProvider?

由于一些特殊要求,我正在实施自定义 ILogger<T>,其中一项要求是在项目 appsettings.jsonLogging 部分内有一个部分,具有该记录器的配置值。问题是,将这些设置注入记录器的正确方法(或好方法)是什么?我想我应该首先在相应的 ILoggerProvider 中注入这些设置,并让提供者使用这些设置实例化一个记录器,但我对如何在提供者中正确注入这些值感到困惑。

到目前为止,我在 Program.cs 中有这个:

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureLogging((context, logging) =>
                {
                    logging.ClearProviders();
                    logging.AddConfiguration(context.Configuration.GetSection("Logging"));
                    logging.AddConsole();
                    logging.AddProvider(new CustomLoggerProvider());
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

appsettings.json中的相关部分是:

"Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "CustomLogger": {
      "Level": "Error",
      "Url": "http://[URL]"
    }
  },

,provider实现如下:

[ProviderAlias("CustomLogger")]
    public class CustomLoggerProvider : ILoggerProvider
    {
        private readonly Dictionary<string, CustomLogger> _loggers;
        private readonly LogLevel _level;
        
        private bool _already_disposed;

        public LogLevel Level
        {
            get => _level;
        }

        public CustomLoggerProvider()
        {
            //Here's where I don't know what should I do to inject the proper config values
            _level = LogLevel.Error;
        }

        public ILogger CreateLogger(string categoryName)
        {
            if (_loggers.ContainsKey(categoryName))
            {
                return _loggers[categoryName];
            }
            var l = new CustomLogger(this);
            _loggers.Add(categoryName, l);
            return l;
        }

        // Rest of implementation omitted for simplicity
    }

我找到了一个可接受的答案,我会 post 放在这里,以备不时之需。

步骤是:

  • 实施您的 ILoggerProviderILogger。 Microsoft 页面上的示例是一个很好的指南。
  • 让您的 ILoggerProvider 实现在其构造函数上接受所需的设置(通过 IOptions<T> 或简单参数;我正在使用一个名为 MyCustomLoggerSettings 的选项对象)。
  • Startup.ConfigureServices() 中将您的 ILoggerProvider 注册为单例,如下所示(假设我的实现称为 MyCustomLoggerProvider):
services.AddSingleton<ILoggerProvider>(p =>
{
    var options = p.GetService<IOptions<MyCustomLoggerSettings>>();
    return new MyCustomLoggerProvider(options);
});

完成。

作为奖励,通过这种方式,您可以将任何其他依赖项传递给该对象(包括在服务集合上注册的对象;services 中接受匿名函数的方法重载的使用为您提供服务集合作为参数,在那里你可以使用 GetService<T> 来解决任何依赖关系。