dependency-injection – 从ILogger访问当前的HttpContext

前端之家收集整理的这篇文章主要介绍了dependency-injection – 从ILogger访问当前的HttpContext前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在ASP.NET Core 1.0中,我有一个ILoggerProvider和ILogger接口的自定义实现.我希望能够从Log方法访问HttpContext.

我似乎需要将IHttpContextAccessor注入自定义ILogger,但无法找到如何做到这一点. ILoggerProvider对象在启动时创建,CreateLogger方法不允许依赖注入.

是否有一种简单的方法可以使用依赖注入ILogger?

@H_502_6@

解决方法

这是一个例子

Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IHttpContextAccessor,HttpContextAccessor>();
    }

    public void Configure(IApplicationBuilder app,ILoggerFactory loggerFactory,IServiceProvider serviceProvider)
    {
        loggerFactory.AddCustomLogger(serviceProvider.GetService<IHttpContextAccessor>());
        // 
    }

自定义记录器:

public class CustomLogProvider : ILoggerProvider
{

    private readonly Func<string,LogLevel,bool> _filter;
    private readonly IHttpContextAccessor _accessor;

    public CustomLogProvider(Func<string,bool> filter,IHttpContextAccessor accessor)
    {
        _filter = filter;
        _accessor = accessor;
    }

    public ILogger CreateLogger(string categoryName)
    {
        return new CustomLogger(categoryName,_filter,_accessor);
    }

    public void Dispose()
    {
    }
}

public class CustomLogger : ILogger
{
    private string _categoryName;
    private Func<string,bool> _filter;
    private readonly IHttpContextAccessor _accessor;

    public CustomLogger(string categoryName,Func<string,IHttpContextAccessor accessor)
    {
        _categoryName = categoryName;
        _filter = filter;
        _accessor = accessor;
    }

    public IDisposable BeginScope<TState>(TState state)
    {
        return null;
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        return (_filter == null || _filter(_categoryName,logLevel));
    }

    public void Log<TState>(LogLevel logLevel,EventId eventId,TState state,Exception exception,Func<TState,Exception,string> formatter)
    {
        if (!IsEnabled(logLevel))
        {
            return;
        }

        if (formatter == null)
        {
            throw new ArgumentNullException(nameof(formatter));
        }

        var message = formatter(state,exception);

        if (string.IsNullOrEmpty(message))
        {
            return;
        }

        message = $"{ logLevel }: {message}";

        if (exception != null)
        {
            message += Environment.NewLine + Environment.NewLine + exception.ToString();
        }
        if(_accessor.HttpContext != null) // you should check HttpContext 
        {
            message += Environment.NewLine + Environment.NewLine + _accessor.HttpContext.Request.Path;
        }
        // your implementation

    }

}
public static class CustomLoggerExtensions
{
    public static ILoggerFactory AddCustomLogger(this ILoggerFactory factory,IHttpContextAccessor accessor,bool> filter = null)
    {
        factory.AddProvider(new CustomLogProvider(filter,accessor));
        return factory;
    }
}

虽然以上方式有效,但我更愿意实现自定义IRequestLogger而不是注入HttpContextAccessor.实现如下(未经测试):

public interface IRequestLogger<T>
{
    void Log(LogLevel logLevel,string message); // you can change this
}

public class RequestLogger<T> : IRequestLogger<T>
{
    private readonly IHttpContextAccessor _accessor;
    private readonly ILogger _logger;
    public RequestLogger(ILogger<T> logger,IHttpContextAccessor accessor)
    {
        _accessor = accessor;
        _logger = logger;
    }

    public void Log(LogLevel logLevel,string message)
    {
        Func<object,string> _messageFormatter = (object state,Exception error) =>
        {
            return state.ToString();
        };
        _logger.Log(LogLevel.Critical,new FormattedLogValues(message),null,_messageFormatter);
    }
}

简单用法

public class LogType
{

}
public void ConfigureServices(IServiceCollection services)
{
     services.AddSingleton<IHttpContextAccessor,HttpContextAccessor>();
     services.AddSingleton(typeof(IRequestLogger<>),typeof(RequestLogger<>));
}

public void Configure(IApplicationBuilder app,ILoggerFactory loggerFactory)
{
     loggerFactory.AddConsole(true);
     app.Run(async (context) =>
     {
         var requestLogger = context.RequestServices.GetService<IRequestLogger<LogType>>();
         requestLogger.Log(LogLevel.Critical,11,"<message>");
         //
     });
}
@H_502_6@ @H_502_6@

猜你在找的asp.Net相关文章