【问题标题】:Use custom async targets with NLog and dependency inject HttpClient使用带有 NLog 和依赖注入 HttpClient 的自定义异步目标
【发布时间】:2022-08-19 01:27:51
【问题描述】:

我正在使用custom async target 在我的 .NET 6 应用程序中使用 NLog (5.0.1.) 将日志写入 Splunk。我想利用IHttpClientFactory in ASP.NET Core

在我的启动.cs, 在下面配置服务(),我注册了我的新目标和 NLog 配置文件。

Target.Register<SplunkTarget>(\"Splunk\");
LogManager.LoadConfiguration(\"NLog.config\");

当我尝试像这样将IHttpClientFactory 注入我的目标班级的讲师时:

private readonly IHttpClientFactory _clientFactory;
public SplunkTarget(IHttpClientFactory clientFactory)
{
     _clientFactory = clientFactory;
}

我无法启动应用程序,因为我收到以下错误:

抛出异常:System.Private.CoreLib.dll 中的 \'System.MissingMethodException\':\'无法动态创建类型为 \'MyNamespace.SplunkTarget\' 的实例。原因:未定义无参数构造函数。\'

如何使用内置的 .NET CoreHttpFactory这样我就不必手动创建Httpclient?

    标签: .net dependency-injection nlog


    【解决方案1】:

    使用 NLog 5.0,您可以在初始化期间解决依赖关系:

    public class MyCustomTarget : AsyncTaskTarget
    {
        protected override void InitializeTarget()
        {
            // ResolveService will throw if dependency is not available,
            // and target-initialization will retry when dependency is available
            var clientFactory = ResolveService<IHttpClientFactory>();
        }
    }
    

    如果目标必须在启动时工作,那么您必须预先注册单例接口:

    NLog.LogManager.Setup().SetupExtensions(ext => ext.RegisterSingletonService<IHttpClientFactory>(clientFactory));
    

    但是您也可以推迟注册,直到调用 UseNLog()AddNLog(),并将 Microsoft ServiceProvider 注册为外部依赖注入提供程序(在此之前生成的所有 LogEvents 都将被缓存并在目标上释放 -初始化成功)。

    另请参阅:https://github.com/NLog/NLog/wiki/Dependency-injection-with-NLog

    附言在 NLog 5.0 之前,可以像这样覆盖工厂方法,并执行依赖注入:

    var defaultConstructor = ConfigurationItemFactory.Default.CreateInstance;
    
    ConfigurationItemFactory.Default.CreateInstance.CreateInstance = type =>
    {
       if (type == typeof(MyCustomTarget))
           return new MyCustomTarget(myCustomParameter);
       
       return defaultConstructor(type);
    };
    

    【讨论】:

    • 我正在使用 NLog 5.0.1。 ResolveService 抛出错误“无法解析类型:'IHttpClientFactory'。必须注册类的实例。'如果我使用 RegisterSingletonService,它应该在自定义目标类中还是在启动时完成?
    • 是的,如果你想避免在第一次初始化尝试时不解析类型的错误,你需要在加载 NLog 配置之前调用RegisterSingletonService。但是请注意,当检测到所需的依赖项可用时,NLog 将自动重试自定义目标的目标初始化(例如来自 AddNLogUseNLog
    【解决方案2】:

    感谢@Rolf Kristensen 的回答和link,我最终做到了这一点。

    在我的启动.cs,在下面配置服务()

    services.AddHttpClient(); // plus all other needed services for DI
    
    // Build the intermediate service provider so that we can pass this to NLog for DI. 
    // Note that all needed services need to be added before this
    var sp = services.BuildServiceProvider();
    NLog.LogManager.Setup().SetupExtensions(ext => ext.RegisterServiceProvider(sp));
    
    
    // I register my new target and NLog configuration file.
    Target.Register<SplunkTarget>("Splunk");
    LogManager.LoadConfiguration("NLog.config");
    

    然后在我的目标类中:

    protected override void InitializeTarget()
    {
        _httpClientFactory = base.ResolveService<IHttpClientFactory>();
        base.InitializeTarget();
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多