Options Pattern (appsettings)

Options pattern - .NET
Learn the options pattern to represent groups of related settings in .NET apps. The options pattern uses classes to provide strongly-typed access to settings.
https://learn.microsoft.com/en-us/dotnet/core/extensions/options

When creating settings you should adhere to

  1. Your service is only dependent upon settings that are used
  1. Different parts of the application are not dependent on each other

Example

Say you want all the settings from within TransientFaultHandlingOptions

{
    "SecretKey": "Secret key value",
    "TransientFaultHandlingOptions": {
        "Enabled": true,
        "AutoRetryDelay": "00:00:07"
    },
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    }
}

You would create a non-abstract public class called for easy ness sake (you will see why in a min) TransientFaultHandlingOptions

public sealed class TransientFaultHandlingOptions
{
    public bool Enabled { get; set; }
    public TimeSpan AutoRetryDelay { get; set; }
}

In the example below we get the environments appsettings, and the generic appsettings

We then create an options object, that gets hydrated when we call GetSection & (Bind or Get<T>)

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using ConsoleJson.Example;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Configuration.Sources.Clear();

IHostEnvironment env = builder.Environment;

builder.Configuration
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);

// Hydrate option 1
TransientFaultHandlingOptions options = new();
builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions))
    .Bind(options);

// OR

// Hydrate option 2
var options =
    builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions))
        .Get<TransientFaultHandlingOptions>();

Console.WriteLine($"TransientFaultHandlingOptions.Enabled={options.Enabled}");
Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={options.AutoRetryDelay}");

// ...

Access via DI

First you will need to bind the option poco to the config

builder.Services.Configure<TransientFaultHandlingOptions>(
    builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions)));

There are 3 DI interfaces that cache options to varying levels:

public sealed class ExampleService(IOptions<TransientFaultHandlingOptions> options)
{
    private readonly TransientFaultHandlingOptions _options = options.Value;

    public void DisplayValues()
    {
        Console.WriteLine($"TransientFaultHandlingOptions.Enabled={_options.Enabled}");
        Console.WriteLine($"TransientFaultHandlingOptions.AutoRetryDelay={_options.AutoRetryDelay}");
    }
}