feat(dependency-injection): add service configuration validation and simplify setup

- Removed unnecessary IConfiguration and SqlServerCacheOptions parameters from AddEnvelopeGenerator
- Added EnsureAllServicesConfigured() to validate that all required service methods are invoked
- Introduced _addingStatus dictionary to track configuration status
- Renamed internal queue field to _serviceRegs for consistency
- Added AddServices() method to explicitly register EnvelopeGenerator services
- Improved AddLocalization() to support optional custom localization options
This commit is contained in:
tekh 2025-11-03 09:30:43 +01:00
parent 22b494a262
commit 3bc5439b5a

View File

@ -11,10 +11,11 @@ namespace EnvelopeGenerator.DependencyInjection;
public static class DependencyInjection public static class DependencyInjection
{ {
public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfiguration config, Action<EGConfiguration> options, Action<SqlServerCacheOptions> distributedCacheOptions) public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, Action<EGConfiguration> options)
{ {
var egConfig = new EGConfiguration(); var egConfig = new EGConfiguration();
options.Invoke(egConfig); options.Invoke(egConfig);
egConfig.EnsureAllServicesConfigured();
egConfig.RegisterAll(services); egConfig.RegisterAll(services);
// Add envelope generator services // Add envelope generator services
@ -29,41 +30,67 @@ public static class DependencyInjection
public record EGConfiguration public record EGConfiguration
{ {
internal readonly Queue<Action<IServiceCollection>> ServiceRegs = new(); internal readonly Queue<Action<IServiceCollection>> _serviceRegs = new();
internal void RegisterAll(IServiceCollection services) internal void RegisterAll(IServiceCollection services)
{ {
while (ServiceRegs.Count > 0) while (_serviceRegs.Count > 0)
ServiceRegs.Dequeue().Invoke(services); _serviceRegs.Dequeue().Invoke(services);
} }
public EGConfiguration AddLocalization() private readonly Dictionary<string, bool> _addingStatus = new ()
{ {
ServiceRegs.Enqueue(s => s.AddLocalization()); { nameof(AddLocalization), false },
{ nameof(AddDistributedSqlServerCache), false },
{ nameof(AddInfrastructure), false },
{ nameof(AddServices), false },
};
public EGConfiguration AddLocalization(Action<IServiceCollection>? customLocalizationOptions = null)
{
_serviceRegs.Enqueue(customLocalizationOptions ?? (s => s.AddLocalization()));
_addingStatus[nameof(AddLocalization)] = true;
return this; return this;
} }
public EGConfiguration AddDistributedSqlServerCache(Action<SqlServerCacheOptions> setupAction) public EGConfiguration AddDistributedSqlServerCache(Action<SqlServerCacheOptions> setupAction)
{ {
ServiceRegs.Enqueue(s => s.AddDistributedSqlServerCache(setupAction)); _serviceRegs.Enqueue(s => s.AddDistributedSqlServerCache(setupAction));
_addingStatus[nameof(AddDistributedSqlServerCache)] = true;
return this; return this;
} }
public EGConfiguration AddInfrastructure(Action<EGInfrastructureConfiguration> options) public EGConfiguration AddInfrastructure(Action<EGInfrastructureConfiguration> options)
{ {
#pragma warning disable CS0618 #pragma warning disable CS0618
ServiceRegs.Enqueue(s => s.AddEGInfrastructureServices(options)); _serviceRegs.Enqueue(s => s.AddEGInfrastructureServices(options));
#pragma warning restore CS0618 #pragma warning restore CS0618
_addingStatus[nameof(AddInfrastructure)] = true;
return this; return this;
} }
public IConfiguration Configuration public EGConfiguration AddServices(IConfiguration config)
{ {
set
{
#pragma warning disable CS0618 #pragma warning disable CS0618
ServiceRegs.Enqueue(s => s.AddEnvelopeGeneratorServices(value)); _serviceRegs.Enqueue(s => s.AddEnvelopeGeneratorServices(config));
#pragma warning restore CS0618 #pragma warning restore CS0618
_addingStatus[nameof(AddServices)] = true;
return this;
}
internal void EnsureAllServicesConfigured()
{
var missingServices = _addingStatus
.Where(kv => !kv.Value)
.Select(kv => kv.Key)
.ToList();
if (missingServices.Count > 0)
{
var missingList = string.Join(", ", missingServices);
throw new InvalidOperationException(
$"Service configuration incomplete. The following required service methods were not called: {missingList}. " +
"Please ensure all necessary configuration methods are invoked before building the application.");
} }
} }
} }