在ASP.NET核心中注册子IOptions

ajsxfq5m  于 2023-03-13  发布在  .NET
关注(0)|答案(3)|浏览(143)

我的配置设置如下:

public void ConfigureServices(IServiceCollection services)
{
    var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
    services.Configure<AppSettings>(configuration);
}

public class AppSettings
{
    public ChildSettings Child { get; set; }

    public string Property { get; set; }
}

public class ChildSettings
{
    public string ChildProperty { get; set; }
}

我的appSettings.json看起来像这样:

{
    "Child": {
        "ChildProperty": "Value"
    }
    "Property": "Value"
}

我可以很好地将IOptions<AppSettings>注入到我的控制器中:

public class MyController : Controller
{
    public MyController(IOptions<AppSettings> options)
    {
        ChildSettings appSettings = options.Value;
    }
}

它有点老了,必须向下走几级才能找到你想要的设置对象。有没有一种方法可以像这样使用IOptions<ChildSettings>

public class MyController : Controller
{
    public MyController(IOptions<ChildSettings> options)
    {
        ChildSettings appSettings = options.Value;
    }
}
wqlqzqxt

wqlqzqxt1#

如果您想直接使用ChildSettings而不通过AppSettings对象,则必须将ChildSettings注册为DI配置中的单独条目,如下所示:
services.Configure<ChildSettings>(_configuration.GetSection("AppSettings:ChildSettings"));
但是如果你想这样做,也许你可以只在appsettings.json文件的根目录下设置ChildSettings,你不需要把你的设置放在一个名为AppSettings的部分。

de90aj5v

de90aj5v2#

配置所有options automatically

PM> Install-Package Register.Options.Asp.Net.Core
  • 启动.cs*
public void ConfigureServices(IServiceCollection services)
{
    services.ConfigureOptionsFromAssemblies(configuration, new List<Assembly>()
    {
        typeof(AppSettings).Assembly
    });

    ...
}
  • 应用程序设置.json*
{
    "ChildSettings": {
        "ChildProperty": "Value"
    }       
}
cl25kdpy

cl25kdpy3#

可以通过实现自定义IOptionsFactory〈〉来实现。
可复制粘贴代码:
用法:services.AddRecursiveOptions<AppSettings>(Configuration);

public static class RecursiveOptionsFactoryExtensions
{
    public static void AddRecursiveOptions<TAppSettings>(this IServiceCollection services, IConfiguration configuration)
        where TAppSettings : class
    {
        var appSettings = configuration.Get<TAppSettings>();
        services.AddSingleton<IAppSettingsProvider>(
            new AppSettingsProvider<TAppSettings>(appSettings!));
        services.AddTransient(typeof(IOptionsFactory<>), typeof(RecursiveResolvingOptionsFactory<>));
        services.Configure<TAppSettings>(configuration);
    }

    private interface IAppSettingsProvider
    {
        public object AppSettings { get; }
    }

    private class AppSettingsProvider<TAppSettings> : IAppSettingsProvider
    {
        public object AppSettings { get; }

        public AppSettingsProvider([DisallowNull] TAppSettings appSettings)
        {
            AppSettings = appSettings ?? throw new ArgumentNullException(nameof(appSettings));
        }
    }

    private class RecursiveResolvingOptionsFactory<TOptions> : IOptionsFactory<TOptions> where TOptions : class, new()
    {
        private readonly IEnumerable<IConfigureOptions<TOptions>> _setups;
        private readonly IEnumerable<IPostConfigureOptions<TOptions>> _postConfigures;
        private readonly IEnumerable<IValidateOptions<TOptions>>? _validations;
        private readonly object _appSettings;

        public RecursiveResolvingOptionsFactory(
            IEnumerable<IConfigureOptions<TOptions>> setups,
            IEnumerable<IPostConfigureOptions<TOptions>> postConfigures,
            IEnumerable<IValidateOptions<TOptions>>? validations,
            IAppSettingsProvider appSettings)
        {
            _setups = setups;
            _postConfigures = postConfigures;
            _validations = validations;
            _appSettings = appSettings.AppSettings;
        }

        private static TOptions? FindOptionsRecursively(object source)
        {
            var properties = source.GetType().GetProperties();
            foreach (var propertyInfo in properties)
            {
                var value = propertyInfo.GetValue(source);
                if (propertyInfo.PropertyType == typeof(TOptions))
                {
                    return (TOptions) value!;
                }

                if (!propertyInfo.PropertyType.IsClass || propertyInfo.PropertyType == typeof(string))
                {
                    continue;
                }

                var found = FindOptionsRecursively(value!);
                if (found != null)
                {
                    return found;
                }
            }

            return null;
        }

        public TOptions Create(string name)
        {
            // instead of creating default instance, like Microsoft.Extensions.Options.OptionsFactory<> does,
            // try finding if it is a property of AppSettings first
            var options = FindOptionsRecursively(_appSettings);
            if (options != null) return options;

            options = new TOptions();

            // copied from Microsoft.Extensions.Options.OptionsFactory<>
            foreach (IConfigureOptions<TOptions> setup in _setups)
            {
                if (setup is IConfigureNamedOptions<TOptions> configureNamedOptions)
                    configureNamedOptions.Configure(name, options);
                else if (name == Options.DefaultName)
                    setup.Configure(options);
            }

            foreach (IPostConfigureOptions<TOptions> postConfigure in _postConfigures)
                postConfigure.PostConfigure(name, options);
            if (_validations != null)
            {
                List<string> failureMessages = new List<string>();
                foreach (IValidateOptions<TOptions> validation in _validations)
                {
                    ValidateOptionsResult validateOptionsResult = validation.Validate(name, options);
                    if (validateOptionsResult.Failed)
                        failureMessages.AddRange(validateOptionsResult.Failures);
                }

                if (failureMessages.Count > 0)
                    throw new OptionsValidationException(name, typeof(TOptions), failureMessages);
            }

            return options;
        }
    }
}

相关问题