C# 如何让NLog将依赖项注入目标?

C# 如何让NLog将依赖项注入目标?,c#,.net-core,dependency-injection,autofac,nlog,C#,.net Core,Dependency Injection,Autofac,Nlog,我有一个自定义NLog日志目标类,如下所示: public class MyTarget : AsyncTaskTarget { public MyTarget() {} public MyTarget(INeedThisThingToFunction thing) { Thing = thing; } public INeedThisThingToFunction Thing { get; set; } public override Ta

我有一个自定义NLog日志目标类,如下所示:

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;
   }
}
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();
}
我不知道如何确保调用第二个构造函数。我已经在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();
}
我也尝试过许多其他的事情,但那是最接近于做某事的。调用
LogManager.Configuration.Reload()
时,将触发
CreateInstance
代码;但是当
Info
方法触发时,目标上的
Thing
属性为空

有更好的方法吗?比如,一种有效的方法


使用.NET Core 3、NLog、Autofac。

如果只有在构建了
主机之后才可以使用
东西,那么您可以这样做:

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;
   }
}
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();
}
然后确保您的自定义
MyTarget
可以处理它是否在“禁用模式”下运行,其中
Thing
未分配:

[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);
   }
}

这回答了你的问题吗?有一个wiki页面:我希望避免使用服务定位器模式,因为在我看来,它似乎违背了DI的目的。如果我能注册我的日志目标并让Autofac正确实例化它们,我会很高兴。或者NLog。@DavidBraverman目前NLog依赖项注入支持相当有限。主要是因为日志记录通常是在依赖项容器完全加载之前设置的。但目前正在努力改善这种情况,因此自定义目标可以在初始化期间解析自定义依赖项(而不是构造函数参数)。希望自动延迟初始化,直到自定义依赖项可用。希望还可以对日志事件进行排队,以便在成功执行初始化后写入日志事件。另请参见(欢迎反馈)不幸的是,这也不起作用。当ConfigureLogging方法运行时,在MyTarget类中正确地设置该对象。但是当LogManager.GetCurrentClassLogger()运行时,MyTarget.Thing属性为null。Autofac是否在不同的上下文或线程中运行?如果不使用服务定位器反模式,就不可能完成我要做的事情吗?@DavidBraverman记住这是
LogManager.Configuration=LogManager.Configuration?.Reload()
而不仅仅是
LogManager.Configuration.Reload()