Options Pattern

Back

Loading concept...

๐ŸŽ›๏ธ The Options Pattern: Your Appโ€™s Personal Settings Butler

๐ŸŒŸ The Big Picture

Imagine you have a magic toy box where you keep all your favorite settings โ€“ like how loud your music should be, what color your room light is, or how many cookies youโ€™re allowed to eat. Now imagine you had a helpful butler who could:

  1. Keep all your settings organized in one place
  2. Make sure your settings make sense (no โ€œ1000 cookiesโ€ allowed!)
  3. Hand you exactly the settings you need, exactly when you need them
  4. Update your settings without restarting your whole day

Thatโ€™s the Options Pattern in ASP.NET! Itโ€™s your appโ€™s personal settings butler. ๐ŸŽฉ


๐Ÿ“ฆ What is the Options Pattern?

The Options Pattern is a clean way to read and use configuration (settings) in your app.

Instead of scattered settings everywhere like:

var timeout = config["Timeout"];
var retries = config["Retries"];

You get a nice organized box:

public class MySettings
{
    public int Timeout { get; set; }
    public int Retries { get; set; }
}

Think of it like organizing your crayons by color instead of throwing them all in one messy pile! ๐Ÿ–๏ธ


๐Ÿงฑ Options Pattern Basics

The Recipe: 3 Simple Steps

Step 1: Create a settings class (your organized box)

public class EmailSettings
{
    public string Server { get; set; }
    public int Port { get; set; }
    public string FromAddress { get; set; }
}

Step 2: Add settings to appsettings.json

{
  "EmailSettings": {
    "Server": "smtp.example.com",
    "Port": 587,
    "FromAddress": "hello@app.com"
  }
}

Step 3: Register and use it

// In Program.cs
builder.Services.Configure<EmailSettings>(
    builder.Configuration
        .GetSection("EmailSettings"));

// In your class
public class Mailer
{
    private readonly EmailSettings _settings;

    public Mailer(
        IOptions<EmailSettings> options)
    {
        _settings = options.Value;
    }
}

๐ŸŽญ The Analogy

Think of a lunch order system:

  • ๐Ÿ“‹ Settings Class = Your lunch form (name, sandwich type, drink)
  • ๐Ÿ“ appsettings.json = The kitchenโ€™s master menu
  • ๐Ÿ”ง Configure() = Telling the kitchen โ€œread section Xโ€
  • ๐ŸŽ IOptions = The butler delivering your lunch
graph TD A["๐Ÿ“ appsettings.json"] --> B["๐Ÿ”ง Configure"] B --> C["๐Ÿ“ฆ Settings Class"] C --> D["๐ŸŽ IOptions"] D --> E["๐ŸŽฏ Your Code"]

โœ… Options Validation: The Bouncer at the Door

Why Validate?

Imagine ordering negative 5 pizzas or setting your alarm for โ€œbanana oโ€™clockโ€. That doesnโ€™t make sense!

Validation is like a bouncer who checks your settings before letting them in:

  • โŒ โ€œPort: -1โ€ โ†’ Rejected!
  • โŒ โ€œTimeout: 0โ€ โ†’ Rejected!
  • โœ… โ€œPort: 587โ€ โ†’ Welcome in!

Two Ways to Validate

Method 1: Data Annotations (Easy!)

public class EmailSettings
{
    [Required]
    public string Server { get; set; }

    [Range(1, 65535)]
    public int Port { get; set; }

    [EmailAddress]
    public string FromAddress { get; set; }
}

Register with validation:

builder.Services
    .AddOptions<EmailSettings>()
    .Bind(builder.Configuration
        .GetSection("EmailSettings"))
    .ValidateDataAnnotations()
    .ValidateOnStart();

Method 2: Custom Validation (Flexible!)

builder.Services
    .AddOptions<EmailSettings>()
    .Bind(builder.Configuration
        .GetSection("EmailSettings"))
    .Validate(settings =>
    {
        return settings.Port > 0
            && !string.IsNullOrEmpty(
                settings.Server);
    }, "Invalid email settings!");

๐ŸŽญ The Analogy

Think of validation like a spelling test for your settings:

  • [Required] = โ€œYou MUST fill in this blankโ€
  • [Range(1, 100)] = โ€œPick a number between 1 and 100โ€
  • ValidateOnStart() = โ€œCheck the test BEFORE class startsโ€
graph TD A["๐Ÿ“ Settings"] --> B{โœ… Valid?} B -->|Yes| C["๐ŸŽฏ App Starts"] B -->|No| D["๐Ÿ’ฅ Error at Startup"]

๐ŸŽ IOptions: The One-Time Photo

What is IOptions?

IOptions<T> gives you your settings once and forever. Itโ€™s like taking a photo of your settings when the app starts.

public class NewsletterService
{
    private readonly EmailSettings _settings;

    public NewsletterService(
        IOptions<EmailSettings> options)
    {
        // This value NEVER changes
        _settings = options.Value;
    }
}

When to Use IOptions?

โœ… Perfect for:

  • Settings that never change while app runs
  • Singleton services (one instance forever)
  • Startup configuration

โŒ Not great for:

  • Settings you want to change without restart
  • Per-request differences

๐ŸŽญ The Analogy

IOptions is like your birth certificate:

  • Created once at the start
  • Never updates
  • Always shows the same information
  • Simple and reliable!

๐Ÿ“ธ IOptionsSnapshot: The Fresh Photo Album

What is IOptionsSnapshot?

IOptionsSnapshot<T> gives you fresh settings for each request. Itโ€™s like checking your photo album where new photos appear!

public class EmailController : Controller
{
    private readonly EmailSettings _settings;

    public EmailController(
        IOptionsSnapshot<EmailSettings>
            options)
    {
        // Fresh value for THIS request
        _settings = options.Value;
    }
}

The Magic: Hot Reload

If you change appsettings.json while the app runs:

  • IOptions โ†’ Still shows OLD values ๐Ÿ“ท
  • IOptionsSnapshot โ†’ Shows NEW values on next request! ๐Ÿ“ธ

When to Use IOptionsSnapshot?

โœ… Perfect for:

  • Scoped services (new instance per request)
  • Controllers and request handlers
  • Settings that might change during runtime

โŒ Not great for:

  • Singleton services (will cause errors!)

๐ŸŽญ The Analogy

IOptionsSnapshot is like a daily newspaper:

  • Each day (request) you get the latest edition
  • Yesterdayโ€™s news is gone
  • Always up-to-date!
graph TD A["Request 1"] --> B["๐Ÿ“ธ Snapshot v1"] C["Config Changes"] --> D["New Values"] E["Request 2"] --> F["๐Ÿ“ธ Snapshot v2"]

๐Ÿ‘€ IOptionsMonitor: The Live Security Camera

What is IOptionsMonitor?

IOptionsMonitor<T> is the most powerful option. It watches your settings like a security camera and tells you the moment something changes!

public class AlertService
{
    private EmailSettings _settings;

    public AlertService(
        IOptionsMonitor<EmailSettings>
            monitor)
    {
        // Always get current value
        _settings = monitor.CurrentValue;

        // Get notified on changes!
        monitor.OnChange(newSettings =>
        {
            _settings = newSettings;
            Console.WriteLine(
                "Settings changed!");
        });
    }
}

Special Power: Change Notifications

// Subscribe to changes
var listener = monitor.OnChange(
    (settings, name) =>
    {
        Console.WriteLine(
            quot;Config '{name}' updated!");
        Console.WriteLine(
            quot;New server: {settings.Server}");
    });

// Later: stop listening
listener.Dispose();

When to Use IOptionsMonitor?

โœ… Perfect for:

  • Singleton services that need live updates
  • Background services running forever
  • When you need change notifications
  • Real-time configuration updates

๐ŸŽญ The Analogy

IOptionsMonitor is like a smart home thermostat:

  • Always shows current temperature
  • Alerts you when temperature changes
  • You can react immediately!
graph TD A["๐Ÿ‘€ IOptionsMonitor"] --> B["CurrentValue"] A --> C["OnChange Event"] D["Config File Changes"] --> A C --> E["๐Ÿ”” Your Handler"]

๐Ÿ”„ Quick Comparison: Which One to Choose?

Feature IOptions IOptionsSnapshot IOptionsMonitor
Lifetime Singleton Scoped Singleton
Reloads? โŒ Never โœ… Per request โœ… Real-time
Change events? โŒ No โŒ No โœ… Yes
Use in Singletons Controllers Background jobs
Analogy ๐Ÿ“ท Photo ๐Ÿ“ฐ Newspaper ๐Ÿ“น Live camera

Decision Tree

graph TD A["Need config?"] --> B{Singleton service?} B -->|Yes| C{Need live updates?} B -->|No| D["IOptionsSnapshot"] C -->|Yes| E["IOptionsMonitor"] C -->|No| F["IOptions"]

๐ŸŒŸ Complete Example: Putting It All Together

Settings Class with Validation

public class AppSettings
{
    [Required]
    public string AppName { get; set; }

    [Range(1, 60)]
    public int TimeoutSeconds { get; set; }

    [Url]
    public string ApiEndpoint { get; set; }
}

Configuration in appsettings.json

{
  "AppSettings": {
    "AppName": "My Awesome App",
    "TimeoutSeconds": 30,
    "ApiEndpoint": "https://api.example.com"
  }
}

Registration in Program.cs

builder.Services
    .AddOptions<AppSettings>()
    .Bind(builder.Configuration
        .GetSection("AppSettings"))
    .ValidateDataAnnotations()
    .ValidateOnStart();

Using All Three Interfaces

// In a Singleton background service
public class BackgroundWorker
{
    public BackgroundWorker(
        IOptionsMonitor<AppSettings> monitor)
    {
        // Can get updates while running
    }
}

// In a Controller
public class HomeController : Controller
{
    public HomeController(
        IOptionsSnapshot<AppSettings> options)
    {
        // Fresh per request
    }
}

// In a startup helper
public class StartupHelper
{
    public StartupHelper(
        IOptions<AppSettings> options)
    {
        // One-time read is fine
    }
}

๐ŸŽฏ Key Takeaways

  1. Options Pattern = Organized settings in typed classes
  2. Validation = Bouncer that checks settings make sense
  3. IOptions = One-time photo (singleton, no reload)
  4. IOptionsSnapshot = Daily newspaper (scoped, reloads per request)
  5. IOptionsMonitor = Live camera (singleton, real-time + events)

The Golden Rules

๐Ÿฅ‡ Use IOptions when settings never change ๐Ÿฅˆ Use IOptionsSnapshot in controllers/scoped services ๐Ÿฅ‰ Use IOptionsMonitor in singletons that need live updates


๐Ÿš€ You Did It!

You now understand the Options Pattern like a pro! Think of yourself as a settings butler master who knows:

  • โœ… How to organize settings neatly
  • โœ… How to validate they make sense
  • โœ… Which โ€œcameraโ€ to use for different situations

Go forth and configure your apps with confidence! ๐ŸŽ‰

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.