Convertendo o appsettings em um objeto com c#

Como converter o appsettings.json em um objeto fortemente tipado no netcore e C#?

Antes de mais nada, vale pontuar que existem várias soluções para esse problema, mas, fui buscar esses dias, a forma mais adequada de trabalhar com os dados de um appsettings. Claro que dependendo do problema, isso não é necessário. Por exemplo, ler apenas uma chave, um texto ou um número. Mas esse caso que vou apresentar, é uma solução para caso você tenha um objeto grande, com uma estrutura de árvore que precise ser manipulado usando o System.Collection.Generic por exemplo.

Vou apresentar um problema para depois apresentar a solução.

Imagine a seguinte estrutura:
{
"Clients": [
{
"name": "pic",
"id": "2378sdkjsk"
},
{
"name": "poc",
"id": "f9d8sdkjsk"
},
{
"name": "pluc",
"id": "n323dj8"
}
]
}


Certo! imaginado... e agora?

Agora você deseja consultar o "client" com "name" = "poc". Blz?

To fazendo sentido? (assisti uma palestra onde o cara repetiu essa pergunta a palestra toda. Em algum número entre o 15 e 20 eu parei de contar).

Para "mapear" esses valores, precisamos primeiro de um objeto. Então criamos um:

namespace PicPocPluc.Models.Configuration
{
public class Clients
{
public string Name { get; set; }
public string Id { get; set; }
}
}

No nosso Startup.cs, geralmente temos as propriedades (se não tem, crie :P):


public IConfiguration Configuration { get; private set; }
public IHostingEnvironment Environment { get; private set; }

E também temos dois métodos:


public Startup(IHostingEnvironment env, IConfiguration configuration);
e
public void ConfigureServices(IServiceCollection services);

Nesses métodos, faremos 2 coisas. A primeira é carregar o appsettings de acordo com nosso ambiente e a segunda é carregar os valores do appsettings na classe "Clients" e oferecer essa classe para nossas controllers via injeção de dependência.

CUMA? Como?

Usando o System.Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), podemos descobrir qual ambientes estamos rodando e com um belo IFzão, vamos carregar o appsettings que queremos no método Startup():


if(System.Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "production"))
Configuration = new ConfigurationBuilder()
.AddJsonFile(Environment.ContentRootPath + @"/appsettings.production.json")
.Build();

Feito isso, teremos o appsettings de cada ambiente funcionando corretamente e o próximo passo é no método ConfigureServices(), carregar nosso objeto:


services.AddSingleton<IConfiguration>(Configuration);
services.AddSingleton(Configuration.GetSection("Clients").Get<List<Clients>>());

Objeto carregado, é hora de usá-lo via injeção de dependência em qualquer controller.

readonly List<Clients> _clients;
public PocController(List<Clients> clients) => _clients = clients;

E pronto ! É isso. Criamos o appsettings com dados, uma classe para mapea-lo, carregamos o appsettings de acordo com o ambiente, usamos a propriedade Configuration do Startup.cs para acessar a chave Clients do appsettings carregado e assim, via injeção de dependência (padrão no netcore), acessamos os dados já carregados no controller. 

Como mencionei no inicio, tem várias formas de fazer. Esse é o formato que usei e me pareceu mais adequado para esse problema. Se te ajudei de alguma forma, valeu escrever o post :)

Abraço!