refactor(di): add AddApplication entry point and generic AddValidatedOptions

- Add Musify.Application.AddApplication(services, config) as the layer's DI
  entry point: registers Mediator, UploadIntentValidator and all app configs
- Collapse the 5 near-identical AddXConfiguration methods into a single
  generic AddValidatedOptions<T>(config, section)
- Move UploadIntentValidator registration out of Infrastructure into the
  Application layer (fixes layering leak); Infra config binding now uses the
  generic helper
- Api calls AddApplication; Worker uses AddValidatedOptions for its configs

Build: 0 warnings, 0 errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-05 04:36:46 +02:00
co-authored by Claude Opus 4.8
parent e802c8565d
commit 38f7094fb0
5 changed files with 47 additions and 69 deletions
@@ -1,57 +1,25 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Musify.Application.Configuration
namespace Musify.Application.Configuration;
public static class ConfigurationDependencyInjection
{
public static class ConfigurationDependencyInjection
public static IServiceCollection AddValidatedOptions<T>(
this IServiceCollection services,
IConfiguration configuration,
string sectionName)
where T : class
{
public static IServiceCollection AddApplicationStorageConfiguration(this IServiceCollection serviceDescriptors, IConfiguration configuration)
{
serviceDescriptors
.AddOptionsWithValidateOnStart<ApplicationStorageConfiguration>()
.Bind(configuration.GetRequiredSection(ApplicationStorageConfiguration.SectionName))
.ValidateDataAnnotations();
serviceDescriptors.AddSingleton(serviceProvider =>
serviceProvider.GetRequiredService<IOptions<ApplicationStorageConfiguration>>().Value);
services
.AddOptionsWithValidateOnStart<T>()
.Bind(configuration.GetRequiredSection(sectionName))
.ValidateDataAnnotations();
return serviceDescriptors;
}
services.AddSingleton(serviceProvider =>
serviceProvider.GetRequiredService<IOptions<T>>().Value);
public static IServiceCollection AddPlayListConfiguration(this IServiceCollection serviceDescriptors, IConfiguration configuration)
{
serviceDescriptors
.AddOptionsWithValidateOnStart<PlayListConfiguration>()
.Bind(configuration.GetRequiredSection(PlayListConfiguration.SectionName))
.ValidateDataAnnotations();
serviceDescriptors.AddSingleton(serviceProvider =>
serviceProvider.GetRequiredService<IOptions<PlayListConfiguration>>().Value);
return serviceDescriptors;
}
public static IServiceCollection AddTrackConfiguration(this IServiceCollection serviceDescriptors, IConfiguration configuration)
{
serviceDescriptors
.AddOptionsWithValidateOnStart<TrackConfiguration>()
.Bind(configuration.GetRequiredSection(TrackConfiguration.SectionName))
.ValidateDataAnnotations();
serviceDescriptors.AddSingleton(serviceProvider =>
serviceProvider.GetRequiredService<IOptions<TrackConfiguration>>().Value);
return serviceDescriptors;
}
public static IServiceCollection AddStreamGatewayConfiguration(this IServiceCollection serviceDescriptors, IConfiguration configuration)
{
serviceDescriptors
.AddOptionsWithValidateOnStart<StreamGatewayConfiguration>()
.Bind(configuration.GetRequiredSection(StreamGatewayConfiguration.SectionName))
.ValidateDataAnnotations();
serviceDescriptors.AddSingleton(serviceProvider =>
serviceProvider.GetRequiredService<IOptions<StreamGatewayConfiguration>>().Value);
return serviceDescriptors;
}
return services;
}
}
}