.NET 6非顶级语句控制台应用Serilog注入后获取实例为null
解决.NET 6控制台应用中无法获取Serilog.ILogger实例的问题
问题根源
AddSerilog方法仅将Serilog集成到Microsoft.Extensions.Logging抽象体系中,DI容器中注册的是Microsoft.Extensions.Logging.ILogger和Microsoft.Extensions.Logging.ILogger<T>类型,并未直接注册Serilog.ILogger。因此直接调用GetService<Serilog.ILogger>()会返回null。
解决方案
方案1:直接将Serilog.ILogger注册到DI容器
修改服务注册代码,在构建服务集合时显式添加Serilog.ILogger的单例注册:
var config = new ConfigurationBuilder() .AddJsonFile("appSettings.json", false, true) .Build(); // 先创建Serilog实例 var logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.File(path: "\\Logs", restrictedToMinimumLevel: LogEventLevel.Information, outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}", fileSizeLimitBytes: 1000000, rollOnFileSizeLimit: true, retainedFileCountLimit: 365, retainedFileTimeLimit: new TimeSpan(365, 0, 0, 0)) .CreateLogger(); var serviceProvider = new ServiceCollection() .AddLogging(builder => { builder.AddSerilog(logger); }) .AddSingleton<Serilog.ILogger>(logger) // 新增:注册Serilog.ILogger到DI .BuildServiceProvider(); // 现在可以正常获取实例 var service = serviceProvider.GetService<Serilog.ILogger>();
方案2:通过Microsoft日志抽象转换为Serilog.ILogger
无需额外注册,先获取Microsoft的ILogger实例,再转换为Serilog.ILogger:
var serviceProvider = new ServiceCollection() .AddLogging(builder => { var logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.File(path: "\\Logs", restrictedToMinimumLevel: LogEventLevel.Information, outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}", fileSizeLimitBytes: 1000000, rollOnFileSizeLimit: true, retainedFileCountLimit: 365, retainedFileTimeLimit: new TimeSpan(365, 0, 0, 0)) .CreateLogger(); builder.AddSerilog(logger); }) .BuildServiceProvider(); // 获取Microsoft ILogger并转换 var msLogger = serviceProvider.GetService<Microsoft.Extensions.Logging.ILogger>(); var serilogLogger = msLogger as Serilog.ILogger; // 或者使用扩展方法(需确保引用Serilog.Extensions.Logging) // var serilogLogger = msLogger.ToSerilogLogger();
推荐方案:使用Microsoft日志抽象进行依赖注入
.NET官方推荐依赖Microsoft.Extensions.Logging.ILogger<T>进行日志注入,Serilog会自动适配该抽象,无需直接操作Serilog.ILogger:
// 定义服务类 public class MyBusinessService { private readonly ILogger<MyBusinessService> _logger; // 注入ILogger<T> public MyBusinessService(ILogger<MyBusinessService> logger) { _logger = logger; } public void Execute() { // 使用Serilog处理日志输出 _logger.LogInformation("业务逻辑执行中"); } } // 注册服务 var serviceProvider = new ServiceCollection() .AddLogging(builder => { var logger = new LoggerConfiguration() .MinimumLevel.Information() .WriteTo.File(path: "\\Logs", restrictedToMinimumLevel: LogEventLevel.Information, outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}", fileSizeLimitBytes: 1000000, rollOnFileSizeLimit: true, retainedFileCountLimit: 365, retainedFileTimeLimit: new TimeSpan(365, 0, 0, 0)) .CreateLogger(); builder.AddSerilog(logger); }) .AddTransient<MyBusinessService>() .BuildServiceProvider(); // 使用服务 var businessService = serviceProvider.GetService<MyBusinessService>(); businessService.Execute();
内容的提问来源于stack exchange,提问作者Rama
相关产品推荐
相关产品推荐

