【问题标题】:Intercept or Decorate calls to ILogger拦截或装饰对 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,而不是我期望的动态代理。

【问题讨论】:

    标签: c# logging castle interception


    【解决方案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);
    }
    

    如果确实有必要,您应该能够继承您感兴趣的工厂(基本上是NLogFactoryExtendedNLogFactory)以覆盖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 实例) - 但我更喜欢你的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-12
    • 1970-01-01
    • 2014-01-07
    • 2018-05-31
    • 1970-01-01
    • 2015-04-13
    • 1970-01-01
    相关资源
    最近更新 更多