Skip to content

Conversation

@fredrikhr
Copy link
Contributor

This PR has been copied from dotnet/extensions#3020

Summary

  • Add BindConfiguration extension method for OptionsBuilder<TOptions>.

Description

There are situations in which the IConfiguration instance from which to configure options has not yet been materialized when a method like ConfigureServices is being executed. For example, the .NET Core Generic Host Builder offers the ConfigureServices method which does not offer access to the Application Configuration instance that will materialize when the Host is built. (Note: A fully materialized host configuration instance can be obtained from the HostBuilderContext instance that is passed to the callback, however, this host configuration can differ from the Application configuration and may not offer the desired behaviour.)

In such situations, the Bind extension methods on the OptionsBuilder<TOptions> cannot be called, since they all require a fully materialized IConfiguration instance. Instead, you need to call the Configure extension method, specifying IConfiguration as a DI dependency for configuration and then call the IConfiguration.Bind extension method in the specifying configuration callback action.

Since binding from a DI-provided IConfiguration is a fairly usual scenario when using the .NET Generic Host (i.e. without using a Startup class), it would be advantageous to simplify this scenario by providing 1st class support in form of an extension method that performs the necessary steps.

Proposal

  • Add BindConfiguration extension method for OptionsBuilder<TOptions>.
namespace Microsoft.Extensions.DependencyInjection
{
// Existing extensions holder type
public static class OptionsBuilderConfigurationExtensions
{
   // New API
   public static OptionsBuilder<TOptions> BindConfiguration<TOptions>(
            this OptionsBuilder<TOptions> optionsBuilder,
            string sectionName = null,
            Action<BinderOptions> configureBinder = null)
            where TOptions : class => null;
}
}

Usage

partial class Startup
{
       public static void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions<MyOptions>()
                .BindConfiguration();
        }
}

Previous implementation

The proposed API is a convenience wrapper around existing APIs. The code above could previously be implemented as follows:

partial class Startup
{
       public static void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions<MyOptions>()
                .Configure<IConfiguration>((opts, config) => config.Bind(opts));
        }
}

Comments

The name BindConfiguration was chosen, since the arguments of the extension method do not directly conway how binding is performed. The existing Bind extension methods all take an IConfiguration instance as argument, and in these cases the binding is implied from the argument type. Conceptually, the proposed API can be thought of as an overload to the existing Bind extension methods.

@Dotnet-GitSync-Bot
Copy link
Collaborator

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@fredrikhr
Copy link
Contributor Author

@Dotnet-GitSync-Bot regarding comment #34191 (comment): The new API have been documented with triple-slash comments

@fredrikhr fredrikhr marked this pull request as ready for review March 27, 2020 15:02
@stephentoub
Copy link
Member

Thank you for the PR. This is adding new public API, which needs to go through the API review process documented at https://github.com/dotnet/runtime/blob/master/docs/project/api-review-process.md. If you're interested in this API being added, please open a new issue that can be used to discuss it; if that API is ultimately approved, we'd welcome you to either re-open this PR or submit a new one with the addition. In the meantime, I'm going to close this. Thanks, again.

@stephentoub stephentoub closed this May 8, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants