I am learning DI in .Net Core and I do not get the idea about the benefit of using IOptions
.
Why do we need IOptions
if we can do without it?
IOptions
interface IService
{
void Print(string str);
}
class Service : IService
{
readonly ServiceOption options;
public Service(IOptions<ServiceOption> options) => this.options = options.Value;
void Print(string str) => Console.WriteLine($"{str} with color : {options.Color}");
}
class ServiceOption
{
public bool Color { get; set; }
}
class Program
{
static void Main()
{
using (ServiceProvider sp = RegisterServices())
{
//
}
}
static ServiceProvider RegisterServices()
{
IServiceCollection isc = new ServiceCollection();
isc.Configure<ServiceOption>(_ => _.Color = true);
isc.AddTransient<IService, Service>();
return isc.BuildServiceProvider();
}
}
IOptions
interface IService
{
void Print(string str);
}
class Service : IService
{
readonly ServiceOption options;
public Service(ServiceOption options) => this.options = options;
public void Print(string str) => Console.WriteLine($"{str} with color : {options.Color}");
}
class ServiceOption
{
public bool Color { get; set; }
}
class Program
{
static void Main()
{
using (ServiceProvider sp = RegisterServices())
{
//
}
}
static ServiceProvider RegisterServices()
{
IServiceCollection isc = new ServiceCollection();
isc.AddSingleton(_ => new ServiceOption { Color = true });
isc.AddTransient<IService, Service>();
return isc.BuildServiceProvider();
}
}
Asp.net core tutorial: Option pattern (IOptions) is used to read the configurations from the appsettings. json file. Option pattern provides, IOption interface that is used to read the setting from the appsettings. json file.
IOptionsMonitor is a Singleton service that retrieves current option values at any time, which is especially useful in singleton dependencies. IOptionsSnapshot is a Scoped service and provides a snapshot of the options at the time the IOptionsSnapshot<T> object is constructed.
IOptions is singleton and hence can be used to read configuration data within any service lifetime. Being singleton, it cannot read changes to the configuration data after the app has started. Run the app and hit the controller action. You should be able to see the values being fetched from the configuration file.
AddOptions(IServiceCollection) Adds services required for using options. AddOptions<TOptions>(IServiceCollection) Gets an options builder that forwards Configure calls for the same named TOptions to the underlying service collection.
In .Net core, it is recommended that all your configurations should be strongly typed based on their use cases. This will help you to achieve separate of concerns.
Practically, you can achieve the same thing without using IOptions as you stated. So, if I go back one step and if we have a look at all the available options in .net core configuration:
1. Raw Configuration[path:key]
You can directly access IConfiguration instance and provide path of JSON key in the accessor part, and the configuration value would be returned.
This is not good approach because there is no strong typing here while reading the configuration.
2. IOptions binding to a Config Section
You can use IOptions implementation (which you already know). This is better because you can have a single class with all related configurations. The IOptions interface provides you additional benefits.
As far as I understood, this IOptions interface decouples your configuration from the actors who are reading the configuration and thereby you can use some additional services from .net core framework.
Please refer MSDN article for details about the benefits.
You can also refer to the twitter conversation at this blog. In that blog, Rick also explains that he could not find any practical case on how this approach is different from the 3rd approach below - as generally the configurations are not dynamic and they are done only once before the application startup.
3. Configuration.Bind() to bind to a Config Section
You can use .Bind call to bind a configuration section to a POCO class. You get strongly typed object. Here if multiple actors are using the configurations, they will not get additional services provided by IOptions interface.
I know this is not exactly pointing out the difference. But I am sure this will bring little more clarity on deciding your preference.
Short answer: yes, you can do without it and access your setting directly from ConfigurationManager.AppSettings
, like in this answer.
Slightly longer answer: especially when you want to test your (Console) Application, it might be nice to inject services and settings.
ASP.NET Core comes with DI included and it will be set up in your Startup.cs
. DI can be used in Console Applications, but it might be hard(er) to set it up, as the default application has no plumbing for it. I wrote a small blog on how to setup DI with IOptions configuration for .NET Core Console Applications.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With