Registering NLog ILogger with Simple Injector

╄→гoц情女王★ 提交于 2019-12-03 11:07:29

You need to define a proxy logger which routes the message to the correct Nlog Logger. This proxy is pretty simple:

public class NLogProxy<T> : ILogger
{
    private static readonly NLog.ILogger logger = 
                 LogManager.GetLogger(typeof (T).FullName);

    void ILogger.Log(string message)
    {
        logger.Log(LogLevel.Info, message);
    }
}

You can register this as

container.RegisterConditional(typeof(ILogger), 
     context => typeof(NLogProxy<>).MakeGenericType(context.Consumer.ImplementationType), 
     Lifestyle.Singleton, context => true);

Everywhere you need logging you only will have to inject ILogger.

As for AOP. I'm unsure what you mean by this comment

A wrapper that has to be maintained (NLog.ILogger contract is huge).

Logging is a cross cutting concern and using a decorator is a great way to apply cross cutting concerns. With a decorator it won't be possible to log every (private) function call entrance and exit but why would you want that? As you can read here you probably don't need that. The simple fact that a service is called (with the data passed to this service) and possible exceptions are logged with the complete stacktrace will be more than sufficient in most cases.

So consider this:

public interface ISomeService
{
    void DoSomething(string someParameter);
}

public class SomeServiceDecorator : ISomeService
{
    private readonly ISomeService decoratee;
    private readonly ILogger logger;

    public SomeServiceDecorator(ISomeService decoratee, ILogger logger)
    {
        this.decoratee = decoratee;
        this.logger = logger;
    }

    public void DoSomething(string someParameter)
    {
        try
        {
            this.logger.Log(string.Format("Do something called with {0}", someParameter));
            this.decoratee.DoSomething(someParameter);
        }
        catch (Exception e)
        {
            this.logger.Log(e.ToString());                
            throw;
        }
    }
}

This decorator will log all function calls with the information passed to the service and will also log any exception.

But this approach would increase the number of classes by 2, so not very DRY. This problem is caused because this design is at least suboptimal. Using a design around a single open generic abstraction will totally solve this problem. You can read about this design here and here.

In this case you would have a single `LoggingDecorator' as

public class LoggingCommandHandlerDecorator<T> : ICommandHandler<T>
{
    private readonly ICommandHandler<T> decoratee;
    private readonly ILogger logger;

    public LoggingCommandHandlerDecorator(ICommandHandler<T> decoratee, ILogger logger)
    {
        this.decoratee = decoratee;
        this.logger = logger;
    }

    public void Handle(T command)
    {
        // serialize command to json and log
        this.logger.Log(serializedcommandData);
        this.decoratee.Handle(command);
    }
}

And this single decorator will log all your commands.

That's my vision of AOP....

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!