Register NLog target (with dependencies) with ASP.NET Core's DI

asp.net-core c# entity-framework-core nlog

Question

I'm using the latest NLog, ASP.NET Core, EF Core.

I wrote a custom log target which saves via EF:

public  class MyEFTarget : TargetWithLayout
{
    private readonly IMyContext _context;

    public MyEFTarget(IMyContext context) : base()
    {
        _context = context;
    }

    protected override void Write(LogEventInfo logEvent)
    {
        // and so on...
    }

}

My Startup:

public void ConfigureServices(IServiceCollection services)
{
  // register context with DI (as scoped)
  services.AddDbContext<MyContext>(o => o.UseSqlite(config.GetConnectionString("Default")));
  services.AddScoped<IMyContext, MyContext>();      

  // target depends on context, so must also be registered with DI
  // I chose scoped so it's the same as the context
  services.AddScoped<MyEFTarget>();

  // ...and so on
}


public void Configure(IApplicationBuilder app, IHostingEnvironment env,
    ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
{
  // normal NLog config 
  env.ConfigureNLog("NLog.config");
  loggerFactory.AddNLog();
  app.AddNLogWeb();

  // register target
  Target.Register<MyEFTarget>("MyEFTarget");

  // add target + rule programmatically
  var target = serviceProvider.GetService<MyEFTarget>();
  var rule = new LoggingRule("*", LogLevel.Info, target);
  LogManager.Configuration.AddTarget("MyEFTarget", target);    // problem is here ********
  LogManager.Configuration.LoggingRules.Add(rule);
  LogManager.ReconfigExistingLoggers();

  // ...and so on
}

The problem is that NLog caches the target instance for the duration of the app...I assume? So it's basically a singleton. And it's keeping a reference to my EF context, which might be disposed.

Is there a better way?

To restate the problem generically (because it's not an EF issue), "how do I register/add a custom target which has short-lived dependencies"?

1
0
3/6/2017 6:03:19 PM

Accepted Answer

When the NLog configuration is loaded, NLog will create an instance of your target with ConfigurationItemFactory.Default.CreateInstance and the target will be only recreated when reloading the configuration.

If you need a new EF context every time, I would recommend to load the EF context in protected override void Write(LogEventInfo logEvent)

1
3/9/2017 11:07:36 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow