Closed ycrumeyrolle closed 7 years ago
@ycrumeyrolle Please take a look at PR #50, as this makes significant changes in support of DI. I hope based on our previous discussions you will probably be happier with the post-DI design than the pre-DI design. :) Thanks!
@bradwilson It is much better, but... I am wondering how to implement an HealthCheck with an existing registered transient service, requiring parameters to check.
services.AddTransient<IWonderfulService, WonderfulService>();
where IWonderfulService
looks like
public interface IWonderfulService
{
void DoSomething(string someValue);
}
I would like to avoid to wrap existing services into a HealthCheckAdapter or something similar.
Adding a HealthCheckContext
parameter to the IHealthCheck.CheckHealthAsync()
would allow to pass values.
Maybe something similar to the AuthZ service ?
I'm not sure what you're after here. You should just be able to ask for the IWonderService
constructor argument to get it for DI. What is the purpose of the context?
What I would like to do :
healthCheckBuilder.AddMyService(testingValue: "special value for test purpose")
I have this kind of interface (basically, a method with value parameter)
// This interface is an existing interface and should not be modified.
public interface IMyService
{
void DoSomething(string someValue);
}
I see two ways to implement a IHealthCheck
for this service.
With a DI-friendly HealthCheck :
public class MyServiceHealthCheckByDI : IHealthCheck
{
private readonly IMyService _myService;
public MyServiceHealthCheck(IMyService service)
{
_myService = service;
}
public async ValueTask<IHealthCheckResult> CheckAsync(CancellationToken cancellationToken = default(CancellationToken))
{
try
{
// How can set this value with the HealthCheckBuilder?
var testingValue = "special value for test purpose";
_myService.DoSomething(testingValue);
return HealthCheckResult.Healthy("OK");
}
catch(Exception e)
{
return HealthCheckResult.Unhealthy(e.ToString());
}
}
}
I do not know how to pass the required value to the HealthCheck.
With a non DI-Friendly HealthCheck :
public class MyServiceHealthCheckWithoutDI : IHealthCheck
{
private readonly IMyService _myService;
private readonly string _testingValue;
public MyServiceHealthCheck(string testingValue)
{
_testingValue = testingValue;
// Not DI Friendly
_myService = new MyServiceImplementation(new MyServiceImplementationDependency(new MyServiceImplementationDependencyDependency(...)));
}
public async ValueTask<IHealthCheckResult> CheckAsync(CancellationToken cancellationToken = default(CancellationToken))
{
try
{
_myService.DoSomething(_testingValue);
return HealthCheckResult.Healthy("OK");
}
catch(Exception e)
{
return HealthCheckResult.Unhealthy(e.ToString());
}
}
}
I can pass the value parameter with the HealthCheck constructor, but it is not DI-compliant anymore...
Registration of services is outside the scope of health checks.
That said, there are lambda versions of DI registration that do what you want:
public static IServiceCollection RegisterMyService(this IServiceCollection serviceCollection, string testingValue)
=> serviceCollection.AddSingleton<IMyService>(serviceProvider => new MyServiceImplementation(testingValue));
Check may support DI on ctor.