2014-09-11 6 views
4

В настоящее время я использую виндзорский замок, а также его средство регистрации в моем приложении.Перехват или украшение звонков в ILogger

Однако в моем протоколе я хотел бы включить некоторую контекстуальную информацию, которая не входит в зарегистрированное сообщение, но сохраняется в пределах CallContext.

Я попытался сделать это путем перехвата вызовов ILogger, используя следующие:

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     var container = new WindsorContainer(); 
     container.AddFacility<LoggingFacility>(f => f.UseNLog()); 
     container.Kernel.Resolver.AddSubResolver(new LoggerResolver(container.Kernel)); 

     var logger = container.Resolve<ILogger>(); 
    } 
} 

public class LoggerResolver: ISubDependencyResolver 
{ 
    private readonly IKernel _kernel; 
    private static ProxyGenerator _proxyGenerator; 

    static LoggerResolver() 
    { 
     _proxyGenerator = new ProxyGenerator(); 
    } 

    public LoggerResolver(IKernel kernel) 
    { 
     _kernel = kernel; 
    } 

    public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) 
    { 
     return dependency.TargetType == typeof(ILogger); 
    } 

    public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) 
    { 
     return _proxyGenerator.CreateInterfaceProxyWithTarget(_kernel.Resolve<ILogger>(), new LoggingInterceptor()); 
    } 
} 

public class LoggingInterceptor: IInterceptor 
{ 
    public void Intercept(IInvocation invocation) 
    { 
     //Some modification to message here 
     invocation.Proceed(); 
    } 
} 

Но переменная logger имеет тип NLog.Loggger, а не динамический прокси я ожидал.

ответ

2

Некоторое копание с помощью ILSpy, похоже, показывает, что вы не сможете перехватить вызовы к экземпляру ILogger. ILogger входом в инстанс создается непосредственно NLogFactory (то же самое для всех заводов лесозаготовительных я посмотрел в, log4net, консоль и т.д.)

// Castle.Services.Logging.NLogIntegration.NLogFactory 
public override ILogger Create(string name) 
{ 
    Logger logger = LogManager.GetLogger(name); 
    return new NLogLogger(logger, this); 
} 

Если это действительно необходимо, вы должны быть в состоянии унаследовать заводы вы заинтересованы в (в основном, NLogFactory и ExtendedNLogFactory), чтобы переопределить создание ILogger. Затем создайте прокси-сервер ILogger на основе экземпляра и подключите свои пользовательские перехватчики. Наконец, сообщите LoggingFacility, что вы хотите использовать произвольную фабрику.

Я начал пессимистически относиться к вашей проблеме, но я нашел решение довольно простым в реализации, поэтому у вас не должно быть слишком много проблем для достижения того, чего вы хотите. Код? Конечно :)

public class MyFactory : NLogFactory 
{ 
    public override ILogger Create(string name) 
    { 
     var il = base.Create(name); 
     var pg = new ProxyGenerator(); 
     return pg.CreateInterfaceProxyWithTarget<ILogger>(il, new LoggingInterceptor()); 
    } 
} 

public class LoggingInterceptor : IInterceptor 
{ 
    public void Intercept(IInvocation invocation) 
    { 
     //Some modification to message here 
     invocation.Proceed(); 
    } 
} 

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     var container = new WindsorContainer(); 
     container.AddFacility<LoggingFacility>(f => f.UseNLog().LogUsing<MyFactory>()); 

     var logger = container.Resolve<ILogger>(); 
     logger.Debug("data"); // we intercept this call, success 
     Console.ReadLine(); 
    } 
} 
+0

Спасибо - я в конечном итоге решить ее в очень похожим образом (я вверх по обновленного экземпляр 'NLogFactory' в реализации' ILoggerFactory') - но я предпочитаю свой метод. – Lawrence