使用Autofac的RegisterGeneric注入NLog

Jer*_*emy 6 c# nlog autofac

注意:更新了建议的改进,更接近但仍然不完全!

与此问题类似 - 使用Autofac传递NLog的声明类的类型 - 我试图将NLog实例注入我的存储库类.

接口:

public interface ILogger<T>
    where T: class
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

执行:

public class NLogger<T> : ILogger<T>
    where T: class
{
    private readonly Logger _logger;

    public NLogger()
    {
        _logger = LogManager.GetLogger(typeof(T).FullName);
    }

    public void Debug(string message)
    {
        _logger.Debug(message);
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

在Autofac注册为:

builder.RegisterGeneric(typeof (NLogger<>)).As(typeof (ILogger<>));
Run Code Online (Sandbox Code Playgroud)

使用断点,我看到Autofac正在创建一堆ILogger/NLogger,其中包含所有各种存储库的正确类型,但生成的日志显示为callsite为"NLog.LoggerImpl.Write".

谢谢你的帮助!


使用泛型的工作解决方案:

public class NLogger<T> : ILogger<T>
    where T: class
{
    private readonly Logger _logger;

    public NLogger()
    {
        _logger = LogManager.GetLogger(typeof(T).FullName);
    }

    public void Debug(string message)
    {
        _logger.Log(typeof(T), new LogEventInfo(LogLevel.Debug, _logger.Name, message));
    }
Run Code Online (Sandbox Code Playgroud)

Jim*_*lla 6

Logger 包装器需要调用 .Log() 并传递附加信息以使 callsite 工作。例如:

_logger.Log(typeof (NLogger<T>), new LogEventInfo(LogLevel.Debug, _logger.Name, null, format, args));
Run Code Online (Sandbox Code Playgroud)

编辑:由于您仍然遇到问题,因此我是这样做的,我知道它的行为是正确的:

public interface ILog
{
    [StringFormatMethodAttribute("format")]
    void Debug(string format, params object[] args);
    [StringFormatMethodAttribute("format")]
    void Info(string format, params object[] args);
    [StringFormatMethodAttribute("format")]
    void Warn(string format, params object[] args);

    [StringFormatMethodAttribute("format")] 
    void Error(string format, params object[] args);
    void Error(Exception ex);

    [StringFormatMethodAttribute("format")]
    void Error(Exception ex, string format, params object[] args);

    [StringFormatMethodAttribute("format")]
    void Fatal(Exception ex, string format, params object[] args);
}

public class NLogLogger : ILog
{
    private readonly Logger _log;

    public NLogLogger(Type type)
    {
        _log = LogManager.GetLogger(type.FullName);
    }

    public void Debug(string format, params object[] args)
    {
        Log(LogLevel.Debug, format, args);
    }

    public void Info(string format, params object[] args)
    {
        Log(LogLevel.Info, format, args);
    }

    public void Warn(string format, params object[] args)
    {
        Log(LogLevel.Warn, format, args);
    }

    public void Error(string format, params object[] args)
    {
        Log(LogLevel.Error, format, args);
    }

    public void Error(Exception ex)
    {
        Log(LogLevel.Error, null, null, ex);
    }

    public void Error(Exception ex, string format, params object[] args)
    {
        Log(LogLevel.Error, format, args, ex);
    }

    public void Fatal(Exception ex, string format, params object[] args)
    {
        Log(LogLevel.Fatal, format, args, ex);
    }

    private void Log(LogLevel level, string format, object[] args)
    {
        _log.Log(typeof (NLogLogger), new LogEventInfo(level, _log.Name, null, format, args));
    }

    private void Log(LogLevel level, string format, object[] args, Exception ex)
    {
        _log.Log(typeof (NLogLogger), new LogEventInfo(level, _log.Name, null, format, args, ex));
    }
}

public class LoggingModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder
            .Register((c, p) => new NLogLogger(p.TypedAs<Type>()))
            .AsImplementedInterfaces();
    }

    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        registration.Preparing +=
            (sender, args) =>
            {
                var forType = args.Component.Activator.LimitType;

                var logParameter = new ResolvedParameter(
                    (p, c) => p.ParameterType == typeof(ILog),
                    (p, c) => c.Resolve<ILog>(TypedParameter.From(forType)));

                args.Parameters = args.Parameters.Union(new[] { logParameter });
            };
    }
}
Run Code Online (Sandbox Code Playgroud)