.NET Framework桌面应用中依赖注入Serilog至SettingsService的错误排查
解决.NET Framework桌面应用中Serilog ILogger依赖注入失败的问题
你遇到的问题核心是DI容器无法解析Serilog的ILogger类型,导致激活SettingsService时抛出异常。这主要是因为你的Serilog配置和Host初始化顺序有误,而且提前关闭了Logger实例,使得DI容器中没有可用的ILogger服务。
问题根源拆解
- 你在创建Host之前就手动实例化了Logger,还调用了
Log.CloseAndFlush()直接关闭了这个实例,后续Host的UseSerilog()无法复用它 - 虽然调用了
.UseSerilog(),但由于之前的Logger已被关闭,DI容器没有正确注册ILogger服务,自然无法注入到SettingsService中
修正方案
我们需要调整Serilog的配置逻辑,让Host统一管理Logger的生命周期,同时确保ILogger被正确注册到DI容器。
步骤1:修正App类的初始化代码
把Logger配置整合到Host的UseSerilog()中,不要提前创建和关闭Logger:
using ReceiptApplication.Services; using Serilog; using System.Windows; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; public App() { _host = Host.CreateDefaultBuilder() .UseSerilog((context, config) => { config .MinimumLevel.Information() .WriteTo.Console() .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day, rollOnFileSizeLimit: true); }) .ConfigureServices((context, services) => { ConfigureServices(services); }) .Build(); } private void ConfigureServices(IServiceCollection services) { services.AddSingleton<ISettingsService, SettingsService>(); services.AddSingleton<newMainWindow>(); } protected override async void OnStartup(StartupEventArgs e) { await _host.StartAsync(); // 现在可以正常获取服务,ILogger会自动注入到SettingsService var newMainWindow = _host.Services.GetRequiredService<newMainWindow>(); newMainWindow.Show(); base.OnStartup(e); } protected override async void OnExit(ExitEventArgs e) { // 应用退出时再关闭Logger,由Host管理生命周期 await _host.StopAsync(); Log.CloseAndFlush(); base.OnExit(e); }
步骤2:优化SettingsService的DI设计
去掉静态Log属性和手动设置方法,完全通过构造函数注入(符合DI规范):
public class SettingsService : ISettingsService { private readonly ILogger _logger; // 构造函数注入ILogger<SettingsService>,自动关联类型上下文 public SettingsService(ILogger<SettingsService> logger) { _logger = logger; _logger.Debug("SettingsService初始化完成"); } public void TestLog() { _logger.Debug("这是SettingsService的测试日志"); } public Settings GetSettings() { return new Settings(); } }
对应的ISettingsService接口也可以移除SetLog方法:
public interface ISettingsService { Settings GetSettings(); void TestLog(); }
关键细节说明
- 用
ILogger<SettingsService>代替ILogger:这是Serilog和Microsoft.Extensions.Logging集成的推荐写法,会自动为Logger添加类型名称作为日志上下文,方便后续排查问题 - 让Host管理Logger生命周期:通过
.UseSerilog()的委托配置方式,Host会负责Logger的创建和销毁,确保DI容器能正确解析ILogger<T>服务 - 不要提前关闭Logger:应该在应用退出的
OnExit方法中调用Log.CloseAndFlush(),避免Logger提前失效
这样修改后,依赖注入就能正常工作,而且完全符合DI规范,不需要再手动设置Logger了。
内容的提问来源于stack exchange,提问作者Sari Rahal
相关产品推荐
相关产品推荐

