You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在IHostBuilder上使用Serilog时遇ILoggerFactory依赖注入错误及过时告警

解决依赖注入无法解析ILoggerFactory的问题

致命错误信息

{"@t":"2023-07-13T06:47:04.5190466Z","@mt":"Host terminated unexpectedly.","@l":"Fatal","@x":"System.InvalidOperationException: Unable to resolve service for type 'Microsoft.Extensions.Logging.ILoggerFactory' while attempting to activate 'VehicleRepairService.Startup'.\r\n   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)\r\n   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)\r\n   at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.UseStartup(Type startupType, HostBuilderContext context, IServiceCollection services, Object instance)\r\n   at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<>c__DisplayClass13_0.<UseStartup>b__0(HostBuilderContext context, IServiceCollection services)\r\n   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()\r\n   at Microsoft.Extensions.Hosting.HostBuilder.Build()\r\n   at VehicleRepairService.Program.Main(String[] args) in C:\\SoleraNA\\Backend\\Inspection\\vehiclerepairservice\\src\\vehiclerepairservice\\Program.cs:line 37"}

原始Program.cs代码

public static IWebHostBuilder CreateHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseSerilog()
                .UseKestrel(k => k.AddServerHeader = false)
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseDefaultServiceProvider(options => options.ValidateScopes = false)
                .UseCloudFoundryHosting()
                // Add VCAP_* configuration data
                .AddCloudFoundry()
                .ConfigureLogging((builderContext, loggingBuilder) =>
                {
                    loggingBuilder.ClearProviders();  // avoid duplicated log entries
                    loggingBuilder.AddSerilogDynamicConsole();
                })
                .UseStartup<Startup>();

过时警告

SerilogWebHostBuilderExtensions.UseSerilog(IWebHostBuilder, ILogger, bool, LoggerProviderCollection)' is obsolete: 'Prefer UseSerilog() on IHostBuilder'

修改后的Program.cs代码

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseSerilog()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseKestrel(k => k.AddServerHeader = false)
                .UseCloudFoundryHosting()
                .AddCloudFoundry()
                .ConfigureLogging((builderContext, loggingBuilder) =>
                {
                    loggingBuilder.ClearProviders();
                    loggingBuilder.AddSerilogDynamicConsole();
                })
                .UseStartup<Startup>();
        });

问题原因与解决方案

原因

改用Host.CreateDefaultBuilder后,Startup类的激活时机发生变化:在Host构建服务提供器的流程中,ILoggerFactory尚未完成注册,而Startup构造函数直接依赖该服务,导致DI容器无法解析。

解决方法

方案1:调整日志配置位置

将ConfigureLogging移到Host级别配置,确保日志服务在Startup激活前完成初始化:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging((context, loggingBuilder) =>
        {
            loggingBuilder.ClearProviders();
            loggingBuilder.AddSerilogDynamicConsole();
        })
        .UseSerilog()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseKestrel(k => k.AddServerHeader = false)
                .UseCloudFoundryHosting()
                .AddCloudFoundry()
                .UseStartup<Startup>();
        });

方案2:修改Startup类的依赖

避免在Startup构造函数中注入ILoggerFactory,改用以下方式:

  • 注入ILogger<Startup>替代(仅需日志记录场景)
  • 在ConfigureServices或Configure方法中获取ILoggerFactory

示例修改后的Startup构造函数:

public class Startup
{
    private readonly IConfiguration _config;
    private readonly ILogger<Startup> _logger;

    public Startup(IConfiguration config, ILogger<Startup> logger)
    {
        _config = config;
        _logger = logger;
    }

    // 其他方法...
}

方案3:保留WebHostBuilder适配Serilog(临时过渡)

若暂时不想切换到HostBuilder,可更新Serilog使用方式消除过时警告:

public static IWebHostBuilder CreateHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseSerilog((context, loggerConfig) =>
        {
            loggerConfig.ReadFrom.Configuration(context.Configuration);
        })
        // 其他原有配置...
        .UseStartup<Startup>();

内容的提问来源于stack exchange,提问作者spindlyCoder832

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:15:16