top of page

Options Pattern in C#: How to supply <IOptions>



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

1 comment
bottom of page