【问题标题】:.NET Core HealthCheck - Add HealthCheck with dependency injection and parameters.NET Core HealthCheck - 使用依赖注入和参数添加 HealthCheck
【发布时间】:2020-10-16 21:50:51
【问题描述】:

我有不同的类继承基类。基类实现接口 IHealthCheck。每个类都有一个构造函数,根据类需要一个记录器和参数。 例如:

public ConnectionHealthCheck(ILogger logger, string address)
        : base(logger)
    {
         Address = address;
    }

我有一个 appSettings.json,它允许我在我的健康检查服务中配置几个诊断。

我在 App.xaml.cs 中获得了诊断列表,我正在尝试将它们添加到 HealthCheck 列表中。

问题是我无法使用旁边的参数进行依赖注入,而且我不知道最好的解决方案是什么......

这是我的代码的一些部分。

OnStartup 方法:

protected override void OnStartup(StartupEventArgs e)
    {
        var a = Assembly.GetExecutingAssembly();
        using var stream = a.GetManifestResourceStream("appsettings.json");

        Configuration = new ConfigurationBuilder()
            .AddJsonStream(stream)
            .Build();

        var host = new HostBuilder()
            .ConfigureHostConfiguration(c => c.AddConfiguration(Configuration))
                .ConfigureServices(ConfigureServices)
                .ConfigureLogging(ConfigureLogging)
                .Build();
       [...] }

configureService 方法:

private void ConfigureServices(IServiceCollection serviceCollection)
    {
        // create and add the healthCheck for each diag in the appSettings file
        List<DiagnosticConfigItem> diagnostics = Configuration.GetSection("AppSettings:Diagnostics").Get<List<DiagnosticConfigItem>>();
        diagnostics.ForEach(x => CreateHealthCheck(serviceCollection, x)); 
        [...] }

还有 CreateHealthCheck 方法问题出在哪里:

private void CreateHealthCheck(IServiceCollection serviceCollection, DiagnosticConfigItem configItem)
    {
        EnumDiagType type;

        try
        {
            type = (EnumDiagType)Enum.Parse(typeof(EnumDiagType), configItem.Type, true);
        }
        catch (Exception)
        {
            throw new Exception("Diagnostic type not supported");
        }

        switch (type)
        {
            case EnumDiagType.Connection:
                serviceCollection.AddHealthChecks().AddCheck(nameof(ConnectionHealthCheck), new ConnectionHealthCheck(???, configItem.Value));
                break;
            case EnumDiagType.Other:
                [...] }

如您所见,我无法创建 ConnectionHealthCheck 类的实例,因为我无法访问 ILogger 对象...

那我该怎么做呢?我考虑了不同的解决方案,但我没有答案或方法

  • 不在 App.xaml.cs 中而是在之后构建 HealthCheck 服务? (在我可以访问 serviceCollection 和记录器的示例视图模型中)

  • 找到一种方法让记录器在 CreateHealthCheck 方法中使用它?

  • 做这样的事情,但我不知道什么时候可以传递参数

    serviceCollection.AddHealthChecks().AddCheck&lt;ConnectionHealthCheck&gt;(nameof(ConnectionHealthCheck));

【问题讨论】:

    标签: c# dependency-injection .net-core-3.1 health-check


    【解决方案1】:

    您可以使用HealthCheckRegistration 来注册您的类(它应该实现IHealthCheck),它具有接受委托Func&lt;IServiceProvider,IHealthCheck&gt; 的构造函数,这允许您使用IServiceProvider 来解析所需的参数以创建您的健康检查类的实例.像这样的:

    public static class ConnectionHealthCheckBuilderExtensions
    {
        const string DefaultName = "example_health_check";
    
        public static IHealthChecksBuilder AddConnectionHealthCheck(
            this IHealthChecksBuilder builder,
            string name = default,
            DiagnosticConfigItem configItem,
            HealthStatus? failureStatus = default,
            IEnumerable<string> tags = default)
        {
            return builder.Add(new HealthCheckRegistration(
                name ?? DefaultName,
                sp => new ConnectionHealthCheck(sp.GetRequiredService<ISomeService>(), configItem.Value),
                failureStatus,
                tags));
        }
    }
    

    有关详细信息,请参阅文档的this 部分。

    【讨论】:

    • 这似乎是一个很好的解决方案,但是当我尝试启动 HealthCheck 时遇到了问题。无法解析生成器中的记录器,我有一个例外:没有注册类型“Microsoft.Extensions.Logging.ILogger”的服务。你知道为什么吗?
    • @Elsassmania 你试图注入/解决不支持的非泛型ILogger,你应该注入/解决ILogger&lt;SomeClass&gt;,在这种情况下ILogger&lt;ConnectionHealthCheck&gt;(实际上也是因为你正在处理手动此解决方案您仍然可以在健康检查的 ctor 中使用 ILogger,但应该解决通用问题:sp.GetRequiredService&lt;ILogger&lt;ConnectionHealthCheck&gt;&gt;())
    • 糟糕!你是对的,我忘记输入 Logger。现在正在运行,感谢您的帮助!
    【解决方案2】:

    .NET Core 内置 DI 可以在构造器级别注入组件。 所以使用以下方式,我在我的 ASP.NET Core 项目中使用。

    public class Startup
    {
        public Startup(IWebHostEnvironment environment, IConfiguration configuration, ILoggerFactory loggerFactory)
        {
            Environment = environment;
            Configuration = configuration;
            LoggerFactory = loggerFactory;
        }
    
        public IConfiguration Configuration { get; }
        public ILoggerFactory LoggerFactory { get; }
        public IWebHostEnvironment Environment { get; }
        
        private void ConfigureServices(IServiceCollection serviceCollection)
        {
            List<DiagnosticConfigItem> diagnostics = Configuration.GetSection("AppSettings:Diagnostics").Get<List<DiagnosticConfigItem>>();
            diagnostics.ForEach(x => CreateHealthCheck(serviceCollection, x, LoggerFactory)); 
        }
        private void CreateHealthCheck(IServiceCollection serviceCollection, DiagnosticConfigItem configItem)
        {
            // Create a ILogger<T> based on your Type by
            loggerFactory.CreateLogger<MessagingServices>())
        }
    }
        
    

    这可能是粗略的,但希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2019-06-29
      • 1970-01-01
      • 2016-05-22
      • 1970-01-01
      • 1970-01-01
      • 2021-10-23
      • 1970-01-01
      • 2021-02-02
      • 1970-01-01
      相关资源
      最近更新 更多