-
Notifications
You must be signed in to change notification settings - Fork 4.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OptionsServiceCollectionExtensions.ConfigureDynamic #45294
Comments
Tagging subscribers to this area: @maryamariyan Issue DetailsBackground and motivationIt is sometimes desired to defined multiple named sections of repeating config blocks in the configuration file. Consider the following configuration which is used to define OAuth2 clients: clients:
google:
clientId: foo
secret: bar
microsoft:
clientId: dotnet
secret: rocks The current approach would require explicitly calling Configure on for each named section, which would require a code change for each new named registration. This new API would allow the entire section to be registered with each entry becoming a named instance. This API is important for dynamically configuring this like authentication schemes. Proposed APInamespace Microsoft.Extensions.DependencyInjection
{
public static class OptionsConfigurationServiceCollectionExtensions
{
+ public static void ConfigureNamedSection<TOptions>(this IServiceCollection services, IConfiguration config) where TOptions : class
+ {
+ services.AddOptions<TOptions>();
+ services.AddSingleton<IConfigureOptions<TOptions>>(new NamedConfigureFromConfigurationSectionNamesOptions<TOptions>(config));
+ } using Microsoft.Extensions.Configuration;
namespace Microsoft.Extensions.Options.ConfigurationExtensions
{
public class NamedConfigureFromConfigurationSectionNamesOptions<TOptions> : IConfigureNamedOptions<TOptions>
where TOptions : class
{
private readonly IConfiguration _config;
public NamedConfigureFromConfigurationSectionNamesOptions(IConfiguration config)
{
_config = config;
}
public void Configure(string name, TOptions options) => _config.GetSection(name).Bind(options);
public void Configure(TOptions options) => Configure(Options.DefaultName, options);
}
} Usage ExamplesGiven the config section above, the registration could look like the following: services.ConfigureNamedSection<OAuth2Options>(_configuration.GetSection("clients")); Alternative DesignsNone considered beyond alternate names for this new API. The naming of the new method can potentially be improved to be more intuitive about what it does. RisksIntroduction of the extra API may cause confusion on its intended usage since it implies a specific structure of the IConfiguration passed in.
|
I think I would prefer to continue adding API to the services.AddOptions<TOptions>()
.BindNameConfiguration("clients"); |
Based on the feedback from @davidfowl, changing the proposal to look as following: namespace Microsoft.Extensions.DependencyInjection
{
public static class OptionsBuilderConfigurationExtensions
{
public static OptionsBuilder<TOptions> BindNameConfiguration<TOptions>(
this OptionsBuilder<TOptions> optionsBuilder,
string configSectionPath)
where TOptions : class
{
_ = optionsBuilder ?? throw new ArgumentNullException(nameof(optionsBuilder));
_ = configSectionPath ?? throw new ArgumentNullException(nameof(configSectionPath));
optionsBuilder.Services.AddSingleton<IConfigureOptions<TOptions>>(sp =>
{
IConfiguration config = sp.GetRequiredService<IConfiguration>();
IConfiguration section = string.Equals("", configSectionPath, StringComparison.OrdinalIgnoreCase)
? config
: config.GetSection(configSectionPath);
return new BindNameConfigurationOptions<TOptions>(section);
});
return optionsBuilder;
} namespace Microsoft.Extensions.Options.ConfigurationExtensions
{
public class BindNameConfigurationOptions<TOptions> : IConfigureNamedOptions<TOptions>
where TOptions : class
{
private readonly IConfiguration _config;
public BindNameConfigurationOptions(IConfiguration config)
{
_config = config;
}
public void Configure(string name, TOptions options) => _config.GetSection(name).Bind(options);
public void Configure(TOptions options) => Configure(Options.DefaultName, options);
}
} |
@davidfowl After trying to use the API as you suggested, I found that it doesn't really fit well together as an extension on
Seems like the logic in Validation, Postconfigure, and other things invoked by |
6.0 is now feature complete, this won't be completed for that release. |
Background and motivation
It is sometimes desired to defined multiple named sections of repeating config blocks in the configuration file. Consider the following configuration which is used to define OAuth2 clients:
The current approach would require explicitly calling Configure on for each named section, which would require a code change for each new named registration. This new API would allow the entire section to be registered with each entry becoming a named instance. This API is important for dynamically configuring this like authentication schemes.
Proposed API
Usage Examples
Given the config section above, the registration could look like the following:
Alternative Designs
None considered beyond alternate names for this new API. The naming of the new method can potentially be improved to be more intuitive about what it does.
Risks
Introduction of the extra API may cause confusion on its intended usage since it implies a specific structure of the IConfiguration passed in.
The text was updated successfully, but these errors were encountered: