How to get the list of IOptions available from DI in c# Core?

前端 未结 2 799
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-15 22:19

Following this post: https://blog.bredvid.no/validating-configuration-in-asp-net-core-e9825bd15f10

I m now available to validate the Settings when a service need it.

相关标签:
2条回答
  • You can get a list of configured option types by iterating the IServiceCollection instance:

    var configuredOptionTypes =
        from descriptor in services
        let serviceType = descriptor.ServiceType
        where serviceType.IsGenericType
        where serviceType.GetGenericTypeDefinition() == typeof(IConfigureNamedOptions<>)
        let optionType = serviceType.GetGenericArguments()[0]
        select optionType;
    
    0 讨论(0)
  • 2021-01-15 22:31

    Following suggestions from Steven, here is my solution: My settings validator service

        public SettingsValidator(
            IServiceProvider services,
            ILifetimeScope scope
        )
        {
            var types = scope.ComponentRegistry.Registrations
                .SelectMany(e => e.Services)
                .Select(s => s as TypedService)
                .Where(s => s.ServiceType.IsAssignableToGenericType(typeof(IConfigureOptions<>)))
                .Select(s => s.ServiceType.GetGenericArguments()[0])
                .Where(s => typeof(ISettings).IsAssignableFrom(s))
                .ToList();
    
            foreach (var t in types)
            {
                var option = services.GetService(typeof(IOptions<>).MakeGenericType(new Type[] { t }));
                option.GetPropertyValue("Value");
            }
        }
    

    in startup:

            builder.RegisterType<SettingsValidator>();
    

    example of Settings

    public class AzureStorageSettings : ISettings
    {
        [Required]
        public string ConnectionString { get; set; }
        [Required]
        public string Container { get; set; }
        [Required]
        public string Path { get; set; }
    }
    

    extensions

    public static class TypeExtensions
    {
        public static bool IsAssignableToGenericType(this Type givenType, Type genericType)
        {
            foreach (var it in givenType.GetInterfaces())
            {
                if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
                    return true;
            }
    
            if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
                return true;
    
            Type baseType = givenType.BaseType;
            if (baseType == null) return false;
    
            return IsAssignableToGenericType(baseType, genericType);
        }
    }
    

    in program.cs

    using (var scope = webHost.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                var logger = services.GetRequiredService<ILogger<Program>>();
                try
                {
                    logger.LogInformation("Starting settings validation.");
                    services.GetRequiredService<SettingsValidator>();
                    logger.LogInformation("The settings have been validated.");
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, "An error occurred while validating the settings.");
                }
            }
    

    Let me know if it works for you too :)

    0 讨论(0)
提交回复
热议问题