skipnothing/.NET Platform

The Options Pattern

An `appsettings.json` section stores `MaxRetries: 3` as text, but a C# class wants it as a real `int`. One line pours those keys into typed properties, and how you read them back has three answers.

  • Bound values arrive typed, but a property with no setter, or a field, silently keeps its default and never throws.
  • The wrapper you inject, not the class, sets freshness: IOptions freezes at startup, IOptionsSnapshot rebinds per request, IOptionsMonitor reads live.
  • Injecting the scoped IOptionsSnapshot into a singleton is illegal; IOptionsMonitor, itself a singleton, is the singleton-safe live reader.
BUILDS ON
01

Bind a Section onto a Class

Reading config["RetryPolicy:MaxRetries"] gives you a string every time, so every consumer parses "3" into an int by hand and hopes the key is spelled right. The options pattern replaces that with a plain class:

public sealed class RetryPolicy
{
    public int MaxRetries { get; set; }
    public TimeSpan Delay { get; set; }
}

One registration line binds a named section onto it:

builder.Services.Configure<RetryPolicy>(
    builder.Configuration.GetSection("RetryPolicy"));

Configure<T> matches each key under the "RetryPolicy" section to a property of the same name and assigns it, converting the stored string to the property's type. Against this JSON:

{ "RetryPolicy": { "MaxRetries": 3, "Delay": "00:00:05" } }

MaxRetries arrives as an int and Delay as a TimeSpan, parsed once at binding, not at every read. The section name is just a string argument: GetSection("Retry") would bind a section named Retry to the same class, so the class name and the section name are independent.

STRING KEYS LAND AS TYPED PROPERTIES

Keep going, sign up to unlock the rest

4 more parts in this topic, plus 25+ more topics in .NET Platform.

Sign up, it's freeSee the full .NET Platform
Configuration & Options0/5#18 The Configuration System
#20 Options Validation