4

私は現在、アプリケーションのロギング機能とともに城のウィンザーを使用しています。

ただし、ログには、ログに記録されたメッセージには含まれていないが、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

4

1 に答える 1

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および)を継承できる必要があります。次に、ILogger のインスタンス ベースのプロキシを作成し、カスタム インターセプターをプラグインします。最後に、カスタム ファクトリを使用することを に通知します。ExtendedNLogFactoryILoggerLoggingFacility

私はあなたの問題について悲観的になり始めましたが、解決策は実装が非常に簡単であることがわかりました。コード?もちろん :)

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();
    }
}
于 2014-09-12T09:50:37.100 に答える