使用依赖项注入的自定义NLog LayoutRenderer与构造函数

Kev*_*inG 5 c# nlog asp.net-core

我正在尝试编写一个自定义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);
    }
}
Run Code Online (Sandbox Code Playgroud)

它正在使用此RequestContext对象:

public class RequestContext
{
    public string CustomValue { get; set; } = "Valid custom value";
}
Run Code Online (Sandbox Code Playgroud)

我还在连接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");
        // ...
    }
Run Code Online (Sandbox Code Playgroud)

然后,我尝试${custom-value}在nlog.config中使用我的设备,但是在AddNLog()通话中出现错误:

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

笔记

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

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

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

我确实看到了此NLog错误,但现在将其标记为已修复,这就是为什么我在这里而不是在那里发布的原因。

为了完整起见,以下是我添加到我的内容中的内容project.json

"dependencies": {
    ...
    "NLog.Extensions.Logging": "1.0.0-*",
    "NLog.Web.AspNetCore": "4.3.0"
},
Run Code Online (Sandbox Code Playgroud)

Jul*_*ian 6

两种方法:

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
};
Run Code Online (Sandbox Code Playgroud)

这是一种更通用的方法。

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

    }
}
Run Code Online (Sandbox Code Playgroud)