自定义NLog LayoutRenderer,带有使用依赖注入的构造函数

时间:2017-02-03 21:37:48

标签: c# asp.net-core nlog

我正在尝试编写一个自定义的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:解析[project-folder] \ 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"
},

2 个答案:

答案 0 :(得分:6)

两种方法:

1)DI意识

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

<p>I hope this html doesn't show up in my new tab!</p>
<div>
<p>This html should show up in my new tab</p>
<a href="somehow only the div I'm in" target="_blank">See HTML of ONLY the div in seperate Tab</a>
</div>

这是一种更通用的方法。

2)AspNetMvcLayoutRendererBase

或者,从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 }; 覆盖(NLog.Web.AspNetCore)并使用AspNetMvcLayoutRendererBase并且不添加构造函数。

仅在需要HttpContextAccessor?.HttpContext?.TryGetRequest()时才有效。

HttpContext

答案 1 :(得分:2)

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

您可能还想考虑使用NLog.Web包中的布局渲染。有几个可以获取特定于请求的信息。甚至可以选择使用HttpContext布局

${aspnet-Item}记录内容

如果这不适合您,也许“有状态”记录器的工作方式与我在此处给出的答案相同:https://stackoverflow.com/a/32857908/1289052