Adding post-configuration – Options, Settings, and Configuration

We must take a similar path to add post-configuration values but implement the IPostConfigureOptions<TOptions> instead. To achieve this, we update the ConfigureAllConfigureMeOptions class to implement that interface:

namespace OptionsConfiguration;
public class ConfigureAllConfigureMeOptions :
    IPostConfigureOptions<ConfigureMeOptions>,
    IConfigureNamedOptions<ConfigureMeOptions>
{
    // Omitted previous code
    public void PostConfigure(string?
name, ConfigureMeOptions options)
    {
        options.Lines = options.Lines.Append(
            $”ConfigureAll:PostConfigure name: {name}”);
    }
}

In the preceding code, we implemented the interface (highlighted lines). The PostConfigure method simply adds a line to the Lines property. To register it with the IoC container, we must add the following line:

builder.Services.AddSingleton<IPostConfigureOptions<ConfigureMeOptions>, ConfigureAllConfigureMeOptions>();

The big difference is that this runs during the post-configuration phase, independent of the initial configuration phase. Executing the application now leads to the following result:

{
  “defaultInstance”: {
    “title”: “Configure Me!”,
    “lines”: [
      “appsettings.json”,
      “ConfigureAll:Configure name: “,
      “ConfigureAll:PostConfigure name: “
    ]
  },
  “namedInstance”: {
    “title”: “Configure Me!”,
    “lines”: [
      “appsettings.json”,
      “ConfigureAll:Configure name: MyNamedInstance”,
      “ConfigureAll:Configure Not Default: MyNamedInstance”,
      “ConfigureAll:PostConfigure name: MyNamedInstance”
    ]
  }
}

In the preceding JSON, the highlighted lines represent our post-configuration code that was added at the end. You might tell yourself, of course, it’s the last line; it’s the last code we registered, which is a legitimate assumption. However, here’s the complete registration code, which clearly shows the IPostConfigureOptions<TOptions> interface was registered first (highlighted), proving the post-configuration code runs last:

builder.Services
    .AddSingleton<IPostConfigureOptions<ConfigureMeOptions>, ConfigureAllConfigureMeOptions>()
    .Configure<ConfigureMeOptions>(builder.Configuration
        .GetSection(“configureMe”))
    .Configure<ConfigureMeOptions>(NamedInstance, builder.Configuration
        .GetSection(“configureMe”))
    .AddSingleton<IConfigureOptions<ConfigureMeOptions>, ConfigureAllConfigureMeOptions>()
;

Next, we create a second configuration class.

Using multiple configurator objects

A very interesting concept with the ASP.NET Core options pattern is that we can register as many configuration classes as we want. This creates many possibilities, including code from one or more assemblies configuring the same options class.Now that we know how this works, let’s add the ConfigureMoreConfigureMeOptions class, which also adds a line to the Lines property:

namespace OptionsConfiguration;
public class ConfigureMoreConfigureMeOptions : IConfigureOptions<ConfigureMeOptions>
{
    public void Configure(ConfigureMeOptions options)
    {
        options.Lines = options.Lines.Append(“ConfigureMore:Configure”);
    }
}

This time, we want that class only to augment the default instance, so it implements the IConfigureOptions<TOptions> interface (highlighted lines).Next, we must register the binding:

builder.Services.AddSingleton<IConfigureOptions<ConfigureMeOptions>, ConfigureMoreConfigureMeOptions>();

As we can see, it’s the same binding but pointing to the ConfigureMoreConfigureMeOptions class instead of the ConfigureAllConfigureMeOptions class.Executing the application and querying the endpoint outputs the following JSON:

{
  “defaultInstance”: {
    “title”: “Configure Me!”,
    “lines”: [
      “appsettings.json”,
      “ConfigureAll:Configure name: “,
      “ConfigureMore:Configure”,
      “ConfigureAll:PostConfigure name: “
    ]
  },
  “namedInstance”: {
    “title”: “Configure Me!”,
    “lines”: [
      “appsettings.json”,
      “ConfigureAll:Configure name: MyNamedInstance”,
      “ConfigureAll:Configure Not Default: MyNamedInstance”,
      “ConfigureAll:PostConfigure name: MyNamedInstance”
    ]
  }
}

The preceding JSON shows the line our new class added to only the default instance (highlighted) before the post-configure option.The possibilities are great, right? The code can contribute configuration objects and register them in one of the two phases to configure options objects. Next, we explore a few more possibilities.

Leave a Reply

Your email address will not be published. Required fields are marked *



         


          Terms of Use | Accessibility Privacy