The IOptions service is used to bind strongly types options class to configuration section and registers it to the Asp.Net Core Dependency Injection Service Container as singleton lifetime. It exposes a Value property which contains your configured TOptions class.
The options pattern is an indirect way to dependency inject settings into a registered service. If you’re using code that implements the options pattern, then you’re required to supply an IOptions<T> object.
For example, let’s say you’re using the MovieService class and it has the following constructor:
public MovieService(IOptions<MovieSettings> options)
This requires you to supply the IOptions<MovieSettings> parameter.
If the settings are in appsettings.json, you can use AddOptions().Bind():
public class Startup
{
//rest of the class
public void ConfigureServices(IServiceCollection services)
{
//rest of method
services.AddOptions<MovieSettings>().Bind
(Configuration.GetSection("MovieSettings"));
}
}
What if you want to supply hardcoded values, or if you want to fetch the settings from somewhere using a registered service (such as a database repository class)? In this article, I’ll show how to supply the IOptions<T> object in these scenarios.
Supply IOptions<T> with hardcoded values
When you’re using code that implements the options pattern, and you want to use hardcoded values, then you can register the Options<T> object and use Options.Create().
For example, let’s say you want to hardcode the MovieSettings values. Here’s how to supply IOptions<MovieSettings> with hardcoded values:
using Microsoft.Extensions.Options;
public class Startup
{
//rest of the class
public void ConfigureServices(IServiceCollection services)
{
//rest of method
services.AddSingleton<IOptions<MovieSettings>>(_ =>
{
return Options.Create(new MovieSettings()
{
MovieAPIUrl = "https://localhost:12345/movies/api"
});
});
}
}
Supply IOptions<T> from a registered service
Let’s say you want to supply IOptions<MovieSettings> by fetching MovieSettings from the database using the registered MovieSettingsRepository service.
There are two approaches for doing that:
Use AddOptions<MovieSettings>().Configure<IMovieSettingsRepository>().
Register IOptions<MovieSettings> directly, allowing you to use Options.Create().
I’ll show both approaches below.
Approach 1 – Use AddOptions<MovieSettings>().Configure<IMovieSettingsRepository>()
With this overload of AddOptions().Configure(), you define a lambda that accepts the MovieSettings object and the resolved IMovieSettingsRepository instance. You can set properties on the MovieSettings object.
public class Startup{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IMovieSettingsRepository,
MovieSettingsRepository>();
services.AddOptions<MovieSettings>()
.Configure<IMovieSettingsRepository>((movieSettings,
movieSettingsRepo) =>
{
movieSettings.MovieAPIUrl =
movieSettingsRepo.GetSettings().MovieAPIUrl;
});
}
}
This approach is good if you only want to set a few of the properties.
Approach 2 – Register IOptions<MovieSettings> directly, allowing you to use Options.Create()
You don’t need to use AddOptions(). You can register IOptions<MovieSettings> directly just like anything else. With this approach, you can resolve the IMovieSettingsRepository instance and use it to create the MovieSettings object and pass it to Options.Create().
using Microsoft.Extensions.Options;
public class Startup
{
//rest of class
public void ConfigureServices(IServiceCollection services)
{
//rest of method
services.AddSingleton<IMovieSettingsRepository,
MovieSettingsRepository>();
services.AddSingleton<IOptions<MovieSettings>>(serviceProvider =>
{
var repo = serviceProvider.GetService
<IMovieSettingsRepository>();
return Options.Create(repo.GetSettings());
});
}
}
This approach gives you full control over how the IOptions<MovieSettings> object is supplied.
Resource: makolyte
The Tech Platform