All of the other answers telling you to manually build an IServiceProvider
to get an IOptions<T>
instance are dangerous because they are wrong (at least as of ASP.NET Core 3.0)! In fact, if you use those answers today, you will get the following compiler warning:
Calling 'BuildServiceProvider' from application code results in an additional copy of singleton services being created. Consider alternatives such as dependency injecting services as parameters to 'Configure'.
The correct way is to accomplish this, which works safely and reliably in all versions of ASP.NET Core, is to implement the IConfigureOptions<TOptions>
interface that's existed since .NET Core 1.0 - but it seems that far too few people know about how it makes things Just Workâ˘.
As an example, you want to add a custom model validator that has a dependency on one of your application's other services. Initially it seems impossible - there's no way to resolve IMyServiceDependency
because you have no access to an IServiceProvider
:
public class MyModelValidatorProvider : IModelValidatorProvider
{
public MyModelValidatorProvider(IMyServiceDependency dependency)
{
...
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.ModelValidatorProviders.Add(new MyModelValidatorProvider(??????));
});
}
But the "magic" of IConfigureOptions<TOptions>
makes it so easy:
public class ConfigureMvcOptions : IConfigureOptions<MvcOptions>
{
private IMyServiceDependency _dependency;
public MyMvcOptions(IMyServiceDependency dependency)
=> _dependency = dependency;
public void Configure(MvcOptions options)
=> options.ModelValidatorProviders.Add(new MyModelValidatorProvider(_dependency));
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
...
// or scoped, or transient, as necessary for your service
services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureMvcOptions>();
}
Essentially, any setup you would have done in the Add***(***Options)
delegates in ConfigureServices
is now moved to your IConfigureOptions<TOptions>
class's Configure
method. Then you register the options in the same way you'd register any other service, and away you go!
For more detail, as well as information on how this works behind the scenes, I refer you to the always-excellent Andrew Lock.