|  |  | 1 |  | using Microsoft.Extensions.Configuration; | 
|  |  | 2 |  | using Microsoft.Extensions.DependencyInjection.Extensions; | 
|  |  | 3 |  |  | 
|  |  | 4 |  | namespace Microsoft.Extensions.DependencyInjection; | 
|  |  | 5 |  |  | 
|  |  | 6 |  | internal delegate void SimpleOptionValid(); | 
|  |  | 7 |  | public static class ExtensionMethods | 
|  |  | 8 |  | { | 
|  |  | 9 |  |     public static IServiceCollection AddSimpleOptions<T>(this IServiceCollection services, | 
|  |  | 10 |  |         string key, | 
|  |  | 11 |  |         Func<T, IServiceProvider, T>? post = null, | 
|  |  | 12 |  |         Action<T, IServiceProvider> validate = null | 
|  |  | 13 |  |         ) where T : class | 
|  | 2 | 14 |  |     { | 
|  | 4 | 15 |  |         post ??= (v, _) => v; | 
|  | 4 | 16 |  |         validate ??= (_, _) => { }; | 
|  |  | 17 |  |  | 
|  | 2 | 18 |  |         services.TryAddKeyedSingleton<T>(key, (sp, _) => | 
|  | 2 | 19 |  |         { | 
|  | 2 | 20 |  |             var configuration = sp.GetRequiredService<IConfiguration>(); | 
|  | 2 | 21 |  |  | 
|  | 2 | 22 |  |             var v = configuration.GetSection(key).Get<T>(option => | 
|  | 2 | 23 |  |             { | 
|  | 2 | 24 |  |                 option.BindNonPublicProperties = true; | 
|  | 4 | 25 |  |             }); | 
|  | 2 | 26 |  |  | 
|  | 2 | 27 |  |             return post.Invoke(v, sp); | 
|  | 4 | 28 |  |         }); | 
|  |  | 29 |  |  | 
|  | 2 | 30 |  |         services.AddTransient<SimpleOptionValid>(sp => | 
|  | 2 | 31 |  |         { | 
|  | 2 | 32 |  |             var v = sp.GetRequiredKeyedService<T>(key); | 
|  | 4 | 33 |  |             return () => validate.Invoke(v, sp); | 
|  | 4 | 34 |  |         }); | 
|  |  | 35 |  |  | 
|  | 2 | 36 |  |         services.AddHostedService<ValidatorHostedService>(); | 
|  |  | 37 |  |  | 
|  | 2 | 38 |  |         return services; | 
|  | 2 | 39 |  |     } | 
|  |  | 40 |  |  | 
|  |  | 41 |  |  | 
|  |  | 42 |  | } | 
|  |  | 43 |  |  | 
|  |  | 44 |  |  |