[英]How to inject dependencies inside an ASP.NET Core Health Check
我正在嘗試使用新的ASP.NET Code 2.2 Healthchecks功能。
在 .net 博客上的此鏈接中,它顯示了一個示例:
public void ConfigureServices(IServiceCollection services)
{
//...
services
.AddHealthChecks()
.AddCheck(new SqlConnectionHealthCheck("MyDatabase", Configuration["ConnectionStrings:DefaultConnection"]));
//...
}
public void Configure(IApplicationBuilder app)
{
app.UseHealthChecks("/healthz");
}
我可以添加實現Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck
接口的自定義檢查。 但是由於我需要向AddCheck
方法提供一個實例而不是一個類型,並且它需要在ConfigureServices
方法中運行,所以我不能在我的自定義檢查器中注入任何依賴項。
有沒有辦法解決這個問題?
從 .NET Core 3.0 開始,注冊更簡單,歸結為
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
services.AddSingleton<SomeDependency>();
services.AddCheck<SomeHealthCheck>("mycheck");
}
請注意,當您使用引擎需要使用的內容時,您不再有單例與瞬態沖突。
支票的名稱是強制性的,因此您必須選擇一張。
雖然接受的 asnwer似乎不再起作用。
如何在 ASP.NET Core Health Check 中注入依賴項。
如果我們以正確的順序注冊我們的服務,那么SomeDependency
將可用於注入SomeHealthCheck
構造函數, SomeHealthCheck
將作為健康檢查功能的一部分運行。
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
services.AddSingleton<SomeDependency>();
// register the custom health check
// after AddHealthChecks and after SomeDependency
services.AddSingleton<IHealthCheck, SomeHealthCheck>();
}
健康檢查示例中的評論指出:
所有 IHealthCheck 服務都可用於健康檢查服務和中間件。 我們建議將所有健康檢查注冊為單例服務。
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
public class SomeDependency
{
public string GetMessage() => "Hello from SomeDependency";
}
public class SomeHealthCheck : IHealthCheck
{
public string Name => nameof(SomeHealthCheck);
private readonly SomeDependency someDependency;
public SomeHealthCheck(SomeDependency someDependency)
{
this.someDependency = someDependency;
}
public Task<HealthCheckResult> CheckHealthAsync(
CancellationToken cancellationToken = default(CancellationToken))
{
var message = this.someDependency.GetMessage();
var result = new HealthCheckResult(HealthCheckStatus.Failed, null, null, null);
return Task.FromResult(result);
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
services.AddSingleton<SomeDependency>();
services.AddSingleton<IHealthCheck, SomeHealthCheck>();
}
public void Configure(IApplicationBuilder app)
{
app.UseHealthChecks("/healthz");
app.Run(async (context) => await context.Response.WriteAsync("Hello World!"));
}
}
此示例也可在此處的 GitHub 上獲得。
除了肖恩的回答:還有一個開放的拉取請求,它允許將任何生命周期(瞬態和范圍)的服務注入健康檢查。 這可能會出現在 2.2 版本中。
當您可以在健康檢查中使用瞬態和范圍服務時,您應該使用瞬態生活方式注冊它們。
我在我的 ASP.NET Core 3.1 Web API 中遇到了這個問題,因為我遵循了上面描述的典型 DI 方法,調用:
services.AddHealthChecks();
services.AddSingleton<IHealthCheck, MyHealthCheck1>();
services.AddSingleton<IHealthCheck, MyHealthCheck2>();
不幸的是,似乎在 ASP.NET Core 3.1 中實際上不起作用,因為我的 IHealthCheck 實現沒有被調用。
相反,我必須在 Startup.ConfigureServices() 中執行以下操作:
services.AddHealthChecks()
.AddCheck<MyHealthCheck1>("My1-check",
HealthStatus.Unhealthy,
new string[] { "tag1" })
.AddCheck<MyHealthCheck2>("My2-check",
HealthStatus.Unhealthy,
new string[] { "tag2" });
然后在 Startup.Configure() 中,我還調用了 MapHealthChecks() 如下:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHealthChecks("/hc");
});
在 asp.net 核心中進行健康檢查的依賴注入的工作方式與通過ServiceProvider
添加的任何其他注冊服務的工作方式完全相同。
這意味着將您的健康檢查創建為
public class Foo : IHealthCheck {
private ILogger<Foo> _log;
public Foo(ILogger<Foo> log) {
_log = log; // log is injected through the DI mechanisms
}
}
並注冊(在這里使用新的 6 樣式):
builder.AddHealthChecks().AddHealthCheck<Foo>();
因此,這也意味着您可以注入IServiceProvider
本身並在需要獲取更多所需服務或奇怪的用例時在內部使用它。
我很好奇為什么文檔中沒有明確說明這一點,也沒有這方面的例子,因為它不是“顯而易見的”。 但它顯然遵循了 asp.net 核心領域中一切的經典模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.