如何使用Autofac注入NLog?WinForm项目报错解决
解决Autofac注入NLog.Logger无公共构造函数的问题
NLog的Logger类没有公共构造函数,它只能通过LogManager的工厂方法创建实例,因此不能让Autofac直接尝试实例化它,得通过工厂模式把Logger实例交给Autofac管理。以下是适配你场景的两种解决方案:
方案1:在泛型日志实现内部直接获取Logger(最简便)
你的LoggerService<T>可以在构造函数里直接调用NLog的工厂方法,获取与泛型类型绑定的Logger,不需要让Autofac注入Logger实例:
public class LoggerService<T> : ILoggerService<T> { private readonly Logger _logger; public LoggerService() { // 获取对应T类型的Logger _logger = LogManager.GetLogger(typeof(T).FullName); } // 实现ILoggerService<T>的日志方法,示例: public void Info(string message) { _logger.Info(message); } }
然后在Autofac模块中只需注册你的泛型服务:
public class AutofacModule : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterGeneric(typeof(LoggerService<>)) .As(typeof(ILoggerService<>)) .SingleInstance(); } }
方案2:让Autofac通过工厂方法注入Logger
如果你希望Logger实例由Autofac统一管理,可以注册Logger的工厂创建逻辑,让Autofac在需要时调用NLog的工厂方法生成实例:
注册全局单例Logger(非泛型)
如果应用不需要按类型区分Logger,可以注册一个全局单例Logger:
builder.Register(c => LogManager.GetCurrentClassLogger()) .As<Logger>() .SingleInstance();
注册泛型Logger(对应你的泛型服务)
如果需要为每个T类型绑定对应的Logger,可通过泛型注册+参数工厂实现:
// 注册泛型Logger,根据依赖类型生成对应实例 builder.RegisterGeneric(typeof(Logger)) .AsSelf() .WithParameter( (pi, ctx) => pi.ParameterType == typeof(Logger), (pi, ctx) => LogManager.GetLogger(pi.Member.DeclaringType.FullName) ) .SingleInstance(); // 注册泛型日志服务,构造函数接收Logger参数 builder.RegisterGeneric(typeof(LoggerService<>)) .As(typeof(ILoggerService<>)) .SingleInstance();
对应的LoggerService<T>构造函数改为注入Logger:
public class LoggerService<T> : ILoggerService<T> { private readonly Logger _logger; public LoggerService(Logger logger) { _logger = logger; } // 实现日志方法... }
关键注意点
- 禁止让Autofac直接实例化
NLog.Logger,必须通过LogManager.GetLogger()或LogManager.GetCurrentClassLogger()获取实例 - 方案1更简洁,适合大多数场景,因为泛型日志服务本身就可以直接关联到对应的Logger类型
内容的提问来源于stack exchange,提问作者AlexSn2020
相关产品推荐
相关产品推荐

