简体   繁体   中英

How can I get NLog to inject dependencies into a target?

I have a custom NLog log target class that looks like this:

public class MyTarget : AsyncTaskTarget
{
   public MyTarget() {}

   public MyTarget(INeedThisThingToFunction thing)
   {
      Thing = thing;
   }

   public INeedThisThingToFunction Thing { get; set; }

   public override Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken cancellationToken)
   {
      Thing.Use();
      return null;
   }
}

I cannot figure out how to ensure that the second constructor gets called. I've done this in Program.cs:

public static void Main(string[] args)
{
   var host = CreateWebHostBuilder(args).Build();
   ConfigureLogging(host.Services.GetAutofacRoot());
   LogManager.GetCurrentClassLogger().Info("Hi mom");
   host.Run();
}

private static void ConfigureLogging(IComponentContext container) {
   ConfigurationItemFactory.Default.CreateInstance = type =>
   {
      if (type != typeof(MyTarget) return Activator.CreateInstance(type);
      var thing = new ThingTheTargetNeedsToFunction();
      return new MyTarget(thing);
   }
   LogManager.Configuration.Reload();
}

I've tried a number of other things, too, but that comes the closest to doing something. When LogManager.Configuration.Reload() is called, the CreateInstance code fires; but when the Info method fires, the Thing property on the target is null.

Is there a better way to do this? Like, a way that works?

Using .NET Core 3, NLog, Autofac.

If the Thing is only available after having built the host , then you can do it like this:

public static void Main(string[] args)
{   
   var host = CreateWebHostBuilder(args).UseNLog().Build();
   ConfigureLogging(host.Services.GetAutofacRoot());
   LogManager.GetCurrentClassLogger().Info("Hi mom");
   host.Run();
}

private static void ConfigureLogging(IComponentContext container)
{
   var defaultConstructor = ConfigurationItemFactory.Default.CreateInstance;
   ConfigurationItemFactory.Default.CreateInstance.CreateInstance = type =>
   {
      if (type == typeof(MyTarget))
      {
          var thing = new ThingTheTargetNeedsToFunction();
          return new MyTarget(thing);
      }

      return defaultConstructor(type);
   };

   // Reload config and assign the newly reloaded config
   LogManager.Configuration = LogManager.Configuration?.Reload();
}

Then make sure that your custom MyTarget can handle that it is running in "disabled mode" where Thing is unassigned:

[Target("MyTarget")] 
public class MyTarget : AsyncTaskTarget
{
   public MyTarget() {}

   public MyTarget(INeedThisThingToFunction thing)
   {
      Thing = thing;
   }

   public INeedThisThingToFunction Thing { get; set; }

   public override await Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken cancellationToken)
   {
      if (Thing == null)
         return null; // Handle that `Thing` is unassigned by default-constructor

      await Thing.UseAsync().ConfigureAwait(false);
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM