加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

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

发布时间:2020-12-15 21:00:11 所属栏目:asp.Net 来源:网络整理
导读:在ASP.NET Core 1.0中,我有一个ILoggerProvider和ILogger接口的自定义实现.我希望能够从Log方法访问HttpContext. 我似乎需要将IHttpContextAccessor注入自定义ILogger,但无法找到如何做到这一点. ILoggerProvider对象在启动时创建,CreateLogger方法不允许依
在ASP.NET Core 1.0中,我有一个ILoggerProvider和ILogger接口的自定义实现.我希望能够从Log方法访问HttpContext.

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

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

解决方法

这是一个例子

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>");
         //
     });
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读