【问题标题】:ILogger<TCategoryName> is never null in api controllerILogger<TCategoryName> 在 api 控制器中从不为空
【发布时间】:2021-10-15 15:50:16
【问题描述】:

我一直在寻求使用 net core 5 将 Serilog 集成到一个新的 API 实现中。我理解它的工作方式是它覆盖了基本的 ILogger 实现并添加了更多功能,这一切都很好并且可以按预期工作。

我遇到的问题是,即使在我的启动中没有指定日志记录实现,I​​Logger 对控制器的依赖也永远不会为空。虽然这可能是一个奇怪的问题,但我希望了解这个 ILogger 的默认实例来自何处。

可以通过在 Visual Studio 中创建一个新的 net core 5 API 来重现该问题,从而获得一个示例 Weather 控制器和一个 Get() 方法。此示例控制器在构造函数中具有 ILogger 依赖项,如下所示;

 public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

然后可以在Action中使用;

 [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            _logger.LogInformation("Testing");

            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }

示例给出了以下program.cs和startup.cs;

  public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication2", Version = "v1" });
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication2 v1"));
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }

 public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

在这段代码中,我们似乎没有添加/定义 Logger,我试图了解它的来源。

在我自己的实现中,我在其他类中依赖 ILogger,这些类在从 API 调用的上下文中工作,但在通过单元测试调用时失败,因为(目前)我没有在其中明确定义 ILogger夹具。

那么 ILogger 在示例 API 中的什么位置进行初始化?

其他API的例子在构造函数中有如下代码,但是如果logger永远不为null,那么.....

 _logger = logger ?? throw new ArgumentNullException(nameof(logger));

【问题讨论】:

  • ILogger&lt;T&gt; 来自使用Host.CreateDefaultBuilder 创建的主机自动注入的日志基础设施。您可以在此处查看更多详细信息:docs.microsoft.com/en-us/aspnet/core/fundamentals/host/…
  • 此外,.NET Core 中的 DI 容器不能注入 null,因此只有在您想切换到另一个 DI 系统时,执行 null 检查才有用为缺失的服务注入 null
  • @CamiloTerevinto 完美,谢谢

标签: c# asp.net-core serilog


【解决方案1】:

调用Host.CreateDefaultBuilder 会添加默认的日志记录。要删除这些默认值,您可以这样做:

Host.CreateDefaultBuilder(args)
  .ConfigureLogging(logging =>
  {
    logging.ClearProviders();
    // Add your own logging provider here.
  })

更多详情可以在这里找到:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-5.0

【讨论】:

  • 删除 Providers 并不会删除 ILogger 实例,它只是意味着 Loggers 集合是空的,当您尝试记录某些内容时不会生成异常,但不会创建任何日志条目。
猜你喜欢
  • 1970-01-01
  • 2018-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-30
  • 1970-01-01
  • 1970-01-01
  • 2013-11-19
相关资源
最近更新 更多