feat: AddValidatedOptions bind+validate+ValidateOnStart

This commit is contained in:
Joseph Doherty
2026-06-01 09:31:14 -04:00
parent 563cf44c60
commit e191893738
2 changed files with 83 additions and 0 deletions
@@ -0,0 +1,36 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace ZB.MOM.WW.Configuration;
/// <summary>DI extensions for binding-and-validating an options section in one call.</summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// Binds <typeparamref name="TOptions"/> to the configuration section at
/// <paramref name="sectionPath"/>, registers <typeparamref name="TValidator"/> as its
/// <see cref="IValidateOptions{TOptions}"/>, and enables <c>ValidateOnStart</c> so a bad
/// configuration fails fast at host startup rather than on first use.
/// </summary>
/// <typeparam name="TOptions">The options type to bind and validate.</typeparam>
/// <typeparam name="TValidator">The validator registered for <typeparamref name="TOptions"/>.</typeparam>
/// <param name="services">The service collection.</param>
/// <param name="configuration">The configuration to bind from.</param>
/// <param name="sectionPath">The configuration section path (e.g. <c>"ScadaBridge:Cluster"</c>).</param>
/// <returns>The <see cref="OptionsBuilder{TOptions}"/> for further chaining.</returns>
public static OptionsBuilder<TOptions> AddValidatedOptions<TOptions, TValidator>(
this IServiceCollection services, IConfiguration configuration, string sectionPath)
where TOptions : class
where TValidator : class, IValidateOptions<TOptions>
{
ArgumentNullException.ThrowIfNull(services);
ArgumentNullException.ThrowIfNull(configuration);
ArgumentException.ThrowIfNullOrWhiteSpace(sectionPath);
services.AddSingleton<IValidateOptions<TOptions>, TValidator>();
return services.AddOptions<TOptions>()
.Bind(configuration.GetSection(sectionPath))
.ValidateOnStart();
}
}