This library enables more fine-grained control for registrations in ServiceProvider. These are especially useful for large complicated application.
It can be critical for a dependency to only be registered once.
You may want to ensure a specfic ASP.NET middleware is only registered once for performance reasons. In large applications (with a lot of dependencies), it may not be obvious what codepaths that registeres middlewares. With this library you can easily specify this requirement and be sure that your application does not run this unneccesary instance of the same middleware.
You may have multiple implementaions of an interface, and you want to be ensure only the proper implementation is registered in a particular context.
There are two separate NuGet packages supplied:
ServiceProviderValidationExtensions
which can be used with àny .NET app (think 'raw' ServiceProvider cases).ServiceProviderValidationExtensions.Hosting
which is designed to be used together withMicrosoft.Extensions.Hosting
(think ServiceProviders used within ASP.NET) .
The following features are supplied:
A service can be registered as exclusive, meaning that not more than once occourence of it can exists in the ServiceProvider.
To register a service as exclusive, call SetExclusiveService
on the IServiceCollection
:
serviceCollection.SetExclusiveService<IMyService>()
Alternatively, overloads for the more common signatures of AddSingleton
, AddScoped
and AddTransient
exists, e.g.:
serviceCollection.AddSingleton<MyService>(ServiceValidation.ExclusiveService);
serviceCollection.AddSingleton<IMyService, MyService>(ServiceValidation.ExclusiveService);
An implementation can be registered as exclusive, meaning that not more than once occourence of the combination of the type of service and the implementation can exists in the ServiceProvider.
To register a service as exclusive, call SetExclusiveImplementation
on the IServiceCollection
:
serviceCollection.SetExclusiveImplementation<IMyService, MyService>()
Alternatively, overloads for the more common signatures of AddSingleton
, AddScoped
and AddTransient
exists, e.g.:
serviceCollection.AddSingleton<IMyService, MyService>(ServiceValidation.ExclusiveService);
The reporting functionality makes it possible to get insights into the registrations in the ServiceProvider. It currently supports detecting duplicate service registrations.
void ConfigureReporting(ReportConfigurer rb)
{
rb.OnDuplicateService(
ds => Console.WriteLine($"{ds.ServiceType} is registered {dsc.ImplementationTypes.Count} times"),
c => c.Except(typeof(IConfigureOptions<>)).Except<ILoggerProvider>());
}
Host.CreateDefaultBuilder()
.UseServiceProviderExtendedValidation(ConfigureReporting)
.Build();
There are two ways of actually invoking the validation, as described below.
In case any validation fails, a ServiceProviderValidationException
is thrown.
Reference the ServiceProviderValidationExtensions.Hosting package and use the UseServiceProviderExtendedValidation
extension method.
Host.CreateDefaultBuilder()
.UseServiceProviderExtendedValidation()
.Build();
or
Host.CreateApplicationBuilder()
.ConfigureContainerWithServiceProviderExtendedValidation()
.Build();
Call BuildServiceProviderWithValidation
on the IServiceCollection
, e.g.
serviceCollection.BuildServiceProviderWithValidation()