Is there a way in ASP.NET to get all singletons?
I want to implement a health check which would instantiate all the registered singletons and only after that return a healthy status.
I am trying to get all the singletons from the IServiceProvider, but it seems to have only one method, i.e. the object? GetService(Type serviceType);.
So, maybe someone knows a way in C# to get all singletons?
I am trying to do like so:
_servicesProvider
.GetServices<object>()
.Where(service => _servicesProvider.GetService(service.GetType()) == service)
But it seems to also give me back scoped services.
Seems like this:
_servicesProvider
.GetServices<object>()
.ToList();
return new HealthCheckResult(HealthStatus.Healthy);
should work. But I am still hoping for a more optimal solution.
I don't believe there is a built in way to do this.
This answer to a similar question agrees, and suggest reflection as a possible solution.
Another option is to register your ServiceCollection with itself via .AddSingleton<IServiceCollection>(serviceCollection). You can then inject this or request it from the IServiceProvider and query it to get all the service descriptions with singleton lifetime:
var serviceCollection = serviceProvider.GetRequiredService<IServiceCollection>();
var singletons = serviceCollection
.Where(descriptor => descriptor.Lifetime == ServiceLifetime.Singleton)
.Select(descriptor => serviceProvider.GetRequiredService(descriptor.ServiceType))
.ToList();
foreach(object singleton in singletons)
{
// do something with the singleton
}
Depending on your use case it may be better to make your own implemention with a reduced interface, rather than exposing all of IServiceCollection to the consumer of the DI container.
@DisplayName already gave an answer that might work as a starting point. Here is a different solution:
IEnumerable<object> singletons = (
from service in services
group service by service.ServiceType into g
where g.Any(descriptor => descriptor.Lifetime == ServiceLifetime.Singleton)
from pair in serviceProvider.GetServices(g.Key).Zip(g)
where pair.Second.Lifetime == ServiceLifetime.Singleton
select pair.First)
.Distinct();
Compared to @DisplayName's answer, this solution will retrieve all registered singletons, even those that are part of a collection. This solution, however, exhibits a few unfortunate downsides that might not exist in @DisplayName's answer:
Pick the solution that works best for your situation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With