【问题标题】:Custom NLog LayoutRenderer with constructor using Dependency Injection使用依赖注入的带有构造函数的自定义 NLog LayoutRenderer
【发布时间】:2017-03-10 06:40:44
【问题描述】:

我正在尝试编写一个自定义 LayoutRenderer 来记录从对象读取的数据,但 NLog 似乎无法与依赖注入一起正常工作。

这是我的 CustomLayoutRenderer:

[LayoutRenderer("custom-value")]
public class CustomLayoutRenderer : LayoutRenderer
{
    private readonly RequestContext _context;

    public CustomLayoutRenderer(RequestContext context)
    {
        _context = context;
    }

    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        builder.Append(_context.CustomValue);
    }
}

它正在使用这个 RequestContext 对象:

public class RequestContext
{
    public string CustomValue { get; set; } = "Valid custom value";
}

我也在连接 DI,配置 NLog 并在 Startup.cs 中注册我的 LayoutRenderer:

    public void ConfigureServices(IServiceCollection services)
    {
        // ...
        services.AddScoped<RequestContext>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        LayoutRenderer.Register<CustomLayoutRenderer>("custom-value");

        loggerFactory.AddNLog();
        app.AddNLogWeb();
        env.ConfigureNLog("nlog.config");
        // ...
    }

然后我尝试在 nlog.config 中使用我的 ${custom-value},但在调用 AddNLog() 时遇到错误:

2017-02-03 13:08:08.0284 从 [project-folder]\bin\Debug\net452\win7-x64\NLog.config 解析配置失败。 异常:NLog.NLogConfigurationException:解析 [项目文件夹]\bin\Debug\net452\win7-x64\NLog.config 时出现异常。 NLog.NLogConfigurationException:无法访问类型的构造函数:ATest.CustomLayoutRenderer。是否授予了所需的权限? 在 NLog.Internal.FactoryHelper.CreateInstance(类型 t) ...

注意事项

我尝试这样做的原因是我想记录一些只能从控制器访问的信息(如 TraceIdentifier、部分 URL 和一些特定于请求的自定义内容)。 RequestContext 中的值将由控制器在收到请求时设置。

以下渲染器按预期工作,这让我认为这是一个依赖注入问题:

[LayoutRenderer("custom-value")]
public class CustomLayoutRenderer : LayoutRenderer
{
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        builder.Append("Hello, World!");
    }
}

我确实看到了这个NLog bug,但它现在被标记为已修复,这就是我在这里而不是那里发帖的原因。

为了完整起见,这是我在project.json 中添加的内容:

"dependencies": {
    ...
    "NLog.Extensions.Logging": "1.0.0-*",
    "NLog.Web.AspNetCore": "4.3.0"
},

【问题讨论】:

    标签: c# asp.net-core nlog


    【解决方案1】:

    两种方法:

    1) DI 感知

    你可以让 NLog DI 知道。添加到您的 startup.cs:

    ConfigurationItemFactory.Default.CreateInstance = (Type type) =>
    { 
        // your custom target. Could be a better check ;)
        if(type == typeof(CustomLayoutRenderer))
          return new CustomLayoutRenderer(...); // TODO get RequestContext
        else
          return Activator.CreateInstance(type); //default
    };
    

    这是一种更通用的方法。

    2) AspNetMvcLayoutRendererBase

    或者,从 AspNetMvcLayoutRendererBase (NLog.Web.AspNetCore) 覆盖并使用 HttpContextAccessor?.HttpContext?.TryGetRequest() 并且不要添加构造函数。

    这仅在需要HttpContext 时有效。

    [LayoutRenderer("custom-value")]
    public class MyCustomRenderer : AspNetLayoutRendererBase
    {
        protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent)
        {
            var httpRequest = HttpContextAccessor?.HttpContext?.TryGetRequest();
    
            if (httpRequest == null)
                return;
    
    
            builder.Append(httpRequest.Something); //TODO
    
        }
    }
    

    【讨论】:

    • 第二种方法好像不行? TryGetRequest() 似乎并不存在于该类上,并且 HttpContextAccessor 在此似乎总是为空。
    • @julian 如果有一个适用于 Microsoft.Extensions.DependencyInjection 或类似的通用解决方案,那就太好了。
    • 我认为您可以将 CreateInstance 与 Microsoft.Extensions.DependencyInjection 结合使用?
    【解决方案2】:

    查看FactoryHelper 的 NLog 源代码。看来您必须提供一个默认构造函数。

    您可能还想考虑使用 NLog.Web 包中的布局渲染。有几个可以获得特定于请求的信息。甚至可以选择使用${aspnet-Item} 布局从HttpContext 记录内容

    如果这不适合您,“有状态”记录器可能会像我在这里给出的答案中那样工作:https://stackoverflow.com/a/32857908/1289052

    【讨论】:

    • 这个问题太乱了。我喜欢你的回答,但我想利用 ASP.NET Core 的内置 DI 系统,所以我不必写我的Sets在每一堂课。我看到我可能可以将${aspnet-Request-Url} 用于我需要的URL 部分,但这是我最后的解决方案。我想以相同的方式设置这个、TraceIdentifier 和我的自定义变量,因为我可以从我的控制器访问所有这些变量。
    猜你喜欢
    • 1970-01-01
    • 2015-07-22
    • 2011-08-26
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    • 2019-07-12
    • 2011-02-02
    相关资源
    最近更新 更多