I know that lots of library code relies on TryAdd*
and TryAddEnumerable
methods to NOT overwrite user-supplied registrations for certain services and only provide default implementations if none have been registered.
However, what if I need to make sure that user code does not/cannot override my library's default service registrations? I've played around with some form of AsStrict
and asked a question here, but this among other shortcomings relies on the user to implement it in his own code-base.
Is there a pattern or general way of structuring AddMyLibrary
so that I can ensure that I have fixed dependencies that the user cannot provide their implementation for.
To ensure that your library's service registrations cannot be overridden by the user, you can use IHostedService
. This approach runs validation at application startup and prevents the user from overriding your critical service registrations.
your service :
public interface IMyService
{
void Execute();
}
public class MyService : IMyService
{
public void Execute()
{
Console.WriteLine("Executing MyService");
}
}
Hosted service for validation:
internal class ValidationHostedService(IServiceProvider serviceProvider) : IHostedService
{
public Task StartAsync(CancellationToken cancellationToken)
{
// Validate required services at application startup
var myService = serviceProvider.GetRequiredService<IMyService>();
if (myService.GetType() != typeof(MyService))
{
throw new InvalidOperationException("IMyService cannot be overridden.");
}
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
// No specific stop logic required
return Task.CompletedTask;
}
}
Service Collection Extension :
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddExampleLibrary(this IServiceCollection services)
{
// Register your library's default service
services.AddSingleton<IMyService, MyService>();
// Register a hosted service for automatic validation
services.AddHostedService<ValidationHostedService>();
return services;
}
}