如何用Autofac注册微软ILogger并自动注入对应类型的ILogger<T>
你的反射实现完全没必要
你反射调用的Operation、ServiceType都属于Autofac的内部非公开API,存在版本升级后内部结构变更导致代码失效的风险,可维护性极差。
最优实现方案
Autofac原生提供了参数匹配的能力,不需要任何私有API反射即可实现需求,分两步即可:
1. 注入对应消费类类型的ILogger
直接注册全局的ResolvedParameter,匹配所有构造函数中的ILogger参数,自动为其创建对应消费类类型的日志实例:
// 先注册ILoggerFactory,直接使用微软扩展的AddLogging即可 builder.AddLogging(); // 全局匹配所有ILogger类型的构造参数,自动创建对应类型的Logger builder.RegisterInstance(new ResolvedParameter( // 匹配条件:参数类型为ILogger (parameterInfo, context) => parameterInfo.ParameterType == typeof(ILogger), // 生成实例:用参数所属的类作为类别创建Logger (parameterInfo, context) => context.Resolve<ILoggerFactory>().CreateLogger(parameterInfo.Member.DeclaringType) )).AsSelf();
这个方案不需要你自定义LogManager<T>,也不需要修改现有类的构造逻辑,MyFactory里注入的ILogger自动就是ILogger<MyFactory>的等效实例,SourceContext会自动设置为MyFactory的完整类名,完全符合你的需求。
2. 携带工作单元通用属性
不建议在Logger创建阶段附加通用Scope属性,正确的做法是在工作单元的入口统一添加:
// 例如在接口请求、任务启动的入口处 public class WorkUnitHandler { private readonly ILogger _logger; public WorkUnitHandler(ILogger logger) => _logger = logger; public async Task Handle(WorkUnit workUnit) { // 统一附加当前工作单元的通用属性 using var scope = _logger.BeginScope(new Dictionary<string, object> { {"OrderNumber", workUnit.OrderNumber}, {"User", workUnit.User} }); // 后续工作单元内所有日志都会自动带上上述Scope属性 // 包括链路中所有类打印的日志 } }
这种实现符合.NET日志的设计规范,Scope的生命周期和工作单元绑定,不会出现属性串用的问题。
内容的提问来源于stack exchange,提问作者nitewulf50
相关产品推荐
相关产品推荐

