拦截或装饰对 ILogger 的调用
Posted
技术标签:
【中文标题】拦截或装饰对 ILogger 的调用【英文标题】:Intercept or Decorate calls to ILogger 【发布时间】:2014-11-05 13:38:44 【问题描述】:我目前正在使用城堡温莎,以及它在我的应用程序中的日志记录工具。
但是,在我的日志记录中,我想包含一些上下文信息,这些信息不在记录的消息中,但存储在 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
,而不是我期望的动态代理。
【问题讨论】:
【参考方案1】:使用 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();
【讨论】:
谢谢 - 我最终以非常相似的方式解决了它(我在ILoggerFactory
的实现中新建了一个 NLogFactory
实例) - 但我更喜欢你的方法。以上是关于拦截或装饰对 ILogger 的调用的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向函数拦截原理 ( 通过修改 GOT 全局偏移表拦截函数 | 通过在实际被调用的函数中添加跳转代码实现函数拦截 )