2014-02-20 6 views
5

Примечание: Обновлено с предлагаемыми улучшениями, ближе, но все еще не совсем там!Инъекция NLog с регистром AutofacGeneric

Как и к этому вопросу - Passing in the type of the declaring class for NLog using Autofac - Я пытаюсь ввести экземпляры NLog в свои классы репозитория.

Интерфейс:

public interface ILogger<T> 
    where T: class 
{ 
    ... 
} 

Реализация:

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); 
    } 

    ... 
} 

Зарегистрировано Autofac как:

builder.RegisterGeneric(typeof (NLogger<>)).As(typeof (ILogger<>)); 

Используя контрольные точки, я вижу, что Autofac создает кучу ILogger/NLogger с правильные типы для всех моих различных репозиториев, но результирующие журналы появляются с ca llsite является «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)); 
    } 
+0

Высоко связанный с этим вопрос: http://stackoverflow.com/questions/7412156/how-to-retain-callsite-information-when-wrapping-nlog – nemesv

+0

Прочитайте это, но я не пытаюсь передать имя класса в качестве конструктора, пытаясь сделать это с помощью дженериков. Подобно 3-летнему ответу от bentayloruk на http://stackoverflow.com/questions/6623431 – Jeremy

+1

Вам все равно нужно сделать то, что описано в связанном вопросе: поэтому вам нужно изменить свой метод отладки на: 'public void Debug (строковое сообщение) { _logger.Log (typeof (NLogger ), новый LogEventInfo (LogLevel.Debug, _logger.Name, message)); } ', чтобы заставить' $ {callsite} 'работать правильно. – nemesv

ответ

4

Logger оберток нужно вызвать .log() и передать дополнительную информацию для callsite работать. Например:

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

EDIT: Поскольку вы все еще возникают проблемы, вот как я это делаю, и я знаю, что это правильно себя:

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 }); 
      }; 
    } 
} 
+1

Закрыть, но должен быть typeof (NLogger ), чтобы работать, спасибо Джим и Немесв, это сделало мой день! – Jeremy

+0

Ну, дерьмо, даже с этим, callsite все еще проходит через «NLog.LoggerImpl.Write» – Jeremy

+0

Я не знаю, почему это так. Я отредактировал свой ответ, чтобы показать, как я использую его в своем проекте, в комплекте с модулем Autofac. Я вообще избегаю общего. –

0

Для тех, кто использует ILogger из Microsoft.Extensions.Logging пространства имен вместе с NLog.Extensions.Logging Пакет Nuget.

public class NLoggerModule : Module 
{ 
    private readonly NLogLoggerProvider _provider; 

    public NLoggerModule() 
    { 
     _provider = new NLogLoggerProvider(); 
    } 

    protected override void Load(ContainerBuilder builder) 
    { 
     builder.Register(CreateLogger).AsImplementedInterfaces(); 
    } 

    private ILogger CreateLogger(IComponentContext c, IEnumerable<Parameter> p) 
    { 
     var logger = _provider.CreateLogger(p.TypedAs<Type>().FullName); 
     return logger; 
    } 

    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) 
    { 
     registration.Preparing += Registration_Preparing; 
    } 

    private void Registration_Preparing(object sender, PreparingEventArgs args) 
    { 
     var forType = args.Component.Activator.LimitType; 

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

     args.Parameters = args.Parameters.Union(new[] { logParameter }); 
    } 
} 
Смежные вопросы