Back to results for “Dependency Injection”
.NET › Dependency Injection

What is the Options pattern's relationship to DI, and how does IOptions<T> itself get resolved through the container?

Advanced

Answer

IOptions<T>, IOptionsSnapshot<T>, and IOptionsMonitor<T> are themselves services resolved through the DI container (registered automatically when you call services.AddOptions() or implicitly via Configure<T>()), demonstrating that the Options pattern is built entirely on top of the standard DI infrastructure rather than being a separate mechanism -- IOptions<T> is registered as Singleton internally, IOptionsSnapshot<T> as Scoped, explaining their respective behavior around configuration change visibility.
// Configure<T> implicitly registers the necessary IOptions<T> infrastructure
builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("Smtp"));

// Under the hood, this makes IOptions<SmtpSettings>, IOptionsSnapshot<SmtpSettings>,
// and IOptionsMonitor<SmtpSettings> all resolvable via the same DI container
Real-world example Understanding that IOptionsSnapshot<T> is registered as Scoped explains precisely why it can't be safely injected into a Singleton service -- it's the exact same captive dependency problem as any other Scoped service being consumed by a Singleton.

Common follow-ups: Why does IOptionsMonitor<T> avoid the captive dependency problem despite being usable in Singletons?;How would you build a custom pattern following these same DI principles?