Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read configuration values from AppSettings and inject the configuration to instances of interface

Just recently, I have been trying out the new asp.net features and came across this issue. I know that we can read the configuration as strongly typed instance. but i have no idea how can i inject the configuration to my class in Microsoft dependency injection.

public interface IProvider
{
  IMyConfiguration Configuration {get;}
  Task Connect();
}

public abstract class Provider: IProvider
{
    private IMyConfiguration _myConfig;

    public Provider(IMyConfiguration config)
    {
        this._myConfig= config;
    }

    public IMyConfiguration Configuration => _myConfig;
    public abstract Task Connect();
}

public class ProviderOne:Provider
{
    public ProviderOne(IMyConfiguration  config) : base(config)
    {
    }

    public Task Connect()
    {
      //implementation
    }
}

configuration class:

public interface IMyConfiguration
{
     string TerminalId { get;set; }
     bool IsDefault {get;set;}
}
public class MyConfiguration : IMyConfiguration
{
     string TerminalId { get;set; }
     bool IsDefault {get;set;}
}

and then in startup.cs as i declared, it is required to pass the MyConfiguration. but i could not find a way to do so. please advice!

public void ConfigureServices(IServiceCollection services)
{
  services.Configure<MyConfiguration>(Configuration.GetSection("MyConfiguration"));
  services.AddSingleton<IProvider>(new ProviderOne(//configuration)); //here is the problem
}
like image 748
Behzad Avatar asked Apr 19 '17 10:04

Behzad


2 Answers

Option 1

First of all, you don't need IMyConfiguration interface. .NET Core already uses own IOptions interface for abstraction. When you use

services.Configure<MyConfiguration>(Configuration.GetSection("MyConfiguration"));

you tell the DI how to resolve next dependency: IOptions<MyConfiguration>

So, instead of

public Provider(IMyConfiguration config)

use

private MyConfiguration _myConfig;

public Provider(IOptions<MyConfiguration> options)
{
    this._myConfig = options.Value;
}

The same for ProviderOne

public ProviderOne(IOptions<MyConfiguration> options) : base(options)

As .NET Core DI knows how to resolve dependencies that are registered, now you can simply use next version of the method:

services.AddSingleton<IProvider, ProviderOne>();

Option 2

You may leave your code as is; directly instantiate instance of MyConfiguration in ConfigureServices method and use for ypur Provider instance creation:

var myConfiguration = new MyConfiguration();
Configuration.GetSection("MyConfiguration").Bind(myConfiguration);

services.AddSingleton<IProvider>(new ProviderOne(myConfiguration));

The main difference is that in this case, you don't use the DI container for ProviderOne instantiation. And so the main disadvantage is that if you need to add more dependencies for your provider (and so extend number of constructor parameters) you should resolve those dependencies in ConfigureServices method as well. For more details, you may find next discussion useful: Best way to resolve during ConfigureServices.

In general, for situation when you have only one implementation of IMyConfiguration, it is possible to do even so:

services.AddSingleton<IMyConfiguration>(myConfiguration);
services.AddSingleton<IProvider, ProviderOne>();

and DI container will understand how to handle that. But as built-in DI container does not allow registering multiple services and then retrieving a specific one, this is not works for you. Some people solve that problem by using the Factory pattern. You will find more in next SO question: How to register multiple implementations of the same interface in Asp.Net Core?

like image 124
Set Avatar answered Nov 03 '22 17:11

Set


  1. Create a class with properties that has to be read from appsettings

Appsettings.json

{
"DecoderClientOptions":
  {
     "url":"[email protected]",
     "key":"A90474-kGAAP1"
  }
}

1.Create a model class.

     public class DecoderClientOptions
        {
            public string url { get; set; }
            public int key { get; set; }
        }
  1. Inject dependency in Startup.cs

         services.Configure<DecoderClientOptions> 
         (Configuration.GetSection(nameof(DecoderClientOptions)));
    
  2. Use the properties in other classes

        public class DecoderClient : IDecoderClient
        {      
            private readonly IOptions<DecoderClientOptions> _ClientOptions;
    
            public DecoderClient(IOptions<DecoderClientOptions> ClientOptions)
            {
                _ClientOptions = ClientOptions;
            }
    
          var url = _ClientOptions.Value.url;
          var key = _ClientOptions.Value.key;
    
like image 35
Dev-lop-er Avatar answered Nov 03 '22 15:11

Dev-lop-er