Home > Enterprise >  How to use multiple sections in one interface asp.net core 6?
How to use multiple sections in one interface asp.net core 6?

Time:04-24

I have multiple sections in my appsettings.json file that in ASP.NET Core 6 application.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "OracleSettings": {
    "Host": "host.com",
    "Port": "1521"
  },
  "ElasticSettings": {
    "Hosts": "elastic.com"
  },
  "RedisSettings": {
    "Ip": "redis.com",
    "Timeout": 1,
    "Duration": 50
  }  
}

And I have created classes for sections.

public class OracleSettings
{
    public string Host { get; set; }
    public string Port { get; set; }
}

public class ElasticSettings
{
    public string Hosts { get; set; }
}

public class RedisSettings
{
    public string Ip { get; set; }
    public int Timout { get; set; }
    public int Duration { get; set; }
}

I want to access all settings using only one interface named IApplciationSettings.

public interface IApplciationSettings
{
    OracleSettings OracleSettings { get; set; }
    ElasticSettings ElasticSettings { get; set; }
    RedisSettings RedisSettings { get; set; }
}

adding the builder services:

builder.Services.Configure<ElasticSettings>(builder.Configuration.GetSection(nameof(ElasticSettings)));
builder.Services.Configure<OracleSettings>(builder.Configuration.GetSection(nameof(OracleSettings)));
builder.Services.Configure<RedisSettings>(builder.Configuration.GetSection(nameof(RedisSettings)));

So I want to bind to IApplciationSettings interface all configurations and use it in constructor dependency injections like following:

[Route("api/[controller]")]
[ApiController]
public class ProductController : ControllerBase
{
    readonly IProductService productService;

    public PoructController(
        IApplciationSettings settings, IProductService productService)
    {
        this.productService = productService;
        
        var oraclesetting = settings.OracleSettings;
    }
}

How can I do this?

CodePudding user response:

Assuming there is a concrete implementation of IApplciationSettings

public class ApplciationSettings : IApplciationSettings {
    public OracleSettings OracleSettings { get; set; }
    public ElasticSettings ElasticSettings { get; set; }
    public RedisSettings RedisSettings { get; set; }
}

Extract the settings directly from configuration and add it to the dependency injection service container.

//...

ApplciationSettings settings = builder.Configuration.Get<ApplciationSettings>();

if(settings == null) throw new Exception("message here"); //fail early

builder.Services.AddSingleton<IApplciationSettings>(settings);

//...

ConfigurationBinder.Get<T> extension method binds and returns the specified type.

Attempts to bind the configuration instance to a new instance of type T. If this configuration section has a value, that will be used. Otherwise binding by matching property names against configuration keys recursively.

This will allow IApplciationSettings to be injected as desired without having to be tightly coupled to IOptions.

Reference Bind hierarchical configuration

CodePudding user response:

You can create your Class base on your IApplicationSettings and in Program you write this:

builder.Services.Configure<ApplicationSettings>(builder.Configuration);

then in your constructor you

[Route("api/[controller]")]
[ApiController]
public class ProductController : ControllerBase
{
    readonly IProductService productService;

    public PoructController(IOptions<ApplicationSettings> settings, IProductService productService)
    {
        this.productService = productService;
        
        var oraclesetting = settings.Value.OracleSettings;
    }
}
  • Related