如何在IHostBuilder.ConfigureLogging中注册带指定参数的自定义LoggingProvider
解决方案
你担心的「ConfigureLogging阶段没有可用的IServiceProvider」不影响你的需求,因为DI容器的工厂注册逻辑是延迟执行的:注册时仅保存工厂委托,不会当场执行,只有容器构建完成首次解析服务时才会调用委托,此时IServiceProvider已经完全可用。
直接修改AddFileWriterLogger扩展方法,使用带工厂重载的ServiceDescriptor.Singleton注册即可,推荐使用ActivatorUtilities简化参数匹配逻辑:
using Microsoft.Extensions.DependencyInjection; public static ILoggingBuilder AddFileWriterLogger(this ILoggingBuilder loggingBuilder, string path) { loggingBuilder.Services.TryAddEnumerable( ServiceDescriptor.Singleton<ILoggerProvider>(serviceProvider => { // 自动从DI容器解析可匹配的构造参数,剩余参数使用手动传入的path return ActivatorUtilities.CreateInstance<FileWriterLoggerProvider>(serviceProvider, path); })); return loggingBuilder; }
ActivatorUtilities.CreateInstance会自动匹配构造函数签名:优先从传入的serviceProvider中解析可获取的参数,剩余未匹配的参数按顺序使用你手动传入的值,无需自己逐个从容器获取依赖,后续修改FileWriterLoggerProvider的构造参数时也不用调整这里的逻辑。
如果你不想依赖ActivatorUtilities,也可以手动获取依赖后实例化:
public static ILoggingBuilder AddFileWriterLogger(this ILoggingBuilder loggingBuilder, string path) { loggingBuilder.Services.TryAddEnumerable( ServiceDescriptor.Singleton<ILoggerProvider>(serviceProvider => { var filterOptions = serviceProvider.GetRequiredService<IOptions<LoggerFilterOptions>>(); return new FileWriterLoggerProvider(serviceProvider, filterOptions, path); })); return loggingBuilder; }
调用方式保持不变
你原来的注册代码不需要做任何修改:
}).ConfigureLogging((hostbuilderContext, loggingBuilder) => { loggingBuilder.ClearProviders(); loggingBuilder.AddFileWriterLogger(loggingPath); // 其余日志配置逻辑 });
内容的提问来源于stack exchange,提问作者Briefkasten
相关产品推荐
相关产品推荐

