Содержание
Когда мы работаем с файловыми провайдерами конфигурации, то настройки в таких файлах могут иметь достаточно разветвленную структуру. В результате, читать такие настройки по одной становится крайне неудобно. Платформа ASP.NET Core позволяет проецировать конфигурационные настройки на классы C#.
Пример проецирования конфигурации ASP.NET Core на класс C#
Путь у нас будет следующий Json-файл конфигурации приложения:
{
"UserName": "Anonymous",
"SecretNumber": 34567
}
Создадим следующий класс для проецирования конфигурации:
public class Options
{
public string UserName { get; set; }
public string SecretNumber { get; set; }
}
Этот класс содержит публичные свойства для чтения/записи, а также конструктор без параметров (по умолчанию). Теперь спроецируем конфигурацию ASP.NET Core на этот класс:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("config.json"); //загружаем конфигурацию
var app = builder.Build();
var options = new Options();
app.Configuration.Bind(options);
app.MapGet("/", () => $"{options.UserName} - {options.SecretNumber}");
app.Run();
Здесь стоит обратить внимание на следующие строки:
var options = new Options(); app.Configuration.Bind(options);
Метод Bind в качестве параметра принимает объект свойства которого должны быть связаны с параметрами конфигурации. Поэтому вначале мы создаем объект класса Options и затем передаем полученный объект в метод Bind.
Альтернативный вариант связывания — использование метода Get следующим образом:
//var options = new Options(); //app.Configuration.Bind(options); var options = app.Configuration.Get<Options>();
В этом случае нет необходимости заранее создавать объект — метод Get вернет его.
Привязка сложных объектов
Рассмотрим конфигурационный файл, который мы создавали ранее:
{
"Settings": {
"Greetings": {
"Ru": "Привет",
"En": "Hello"
},
"UserName": "Anonymous",
"SecretNumber": 34567
}
}
Такой файл конфигурации имеет уже более сложную структуру. Чтобы спроецировать такую конфигурацию на класс C#, этот класс должен содержать в качестве свойства другой класс и выглядеть следующим образом:
public class Greetings
{
public string? En { get; set; }
public string? Ru { get; set; }
}
public class Settings
{
public Greetings? Greetings { get; set; }
public string? UserName { get; set; }
public string? SecretNumber { get; set; }
}
public class Options
{
public Settings? Settings { get; set; }
}
Теперь спроецируем конфигурацию на класс Options:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("config.json");
var app = builder.Build();
var options = app.Configuration.Get<Options>();
app.MapGet("/", () => $"{options.Settings.UserName} - {options.Settings.SecretNumber} - {options.Settings?.Greetings?.Ru}");
Проецирование отдельных секций на классы C#
Не всегда удобно проецировать весь файл целиком на класс C#. Например, если мы добавляем настройки в стандартный json-файл appsettings.json, то нам может не потребоваться считывать уже имеющиеся там по умолчанию настройки. В этом случае мы можем спроецировать отдельную секцию на класс C#. Рассмотрим следующий пример:
{
"Settings": {
"Greetings": {
"Ru": "Привет",
"En": "Hello"
},
"UserName": "Anonymous",
"SecretNumber": 34567
},
"Data": {
"Element": "Task",
"Id": 2,
"Sections": ["Main","Primary"]
}
}
Попробуем спроецировать на класс C# только секцию Data:
public class DataOptions
{
public string Element { get; set; } //"Element": "Task",
public int Id { get; set; } //"Id": 2,
public List<string> Sections { get; set; } = new(); // "Sections": ["Main","Primary"]
}
Теперь проецируем секцию на класс C#:
builder.Configuration.AddJsonFile("config.json");
var app = builder.Build();
var options = app.Configuration.GetSection("Data").Get<DataOptions>();
Считываем настройки из полученного объекта:
app.MapGet("/", () => $"{options.Id} - {options.Element} \n {string.Join("\n", options.Sections)}");
С помощью метода GetSection() мы получаем необходимую нам секцию конфигурации и затем также вызываем метод Get чтобы выполнить привязку.
Итого
ASP.NET Core предоставляет нам удобный механизм проецирования конфигурации на классы C#. Такой подход удобно использовать, когда конфигурация имеет сложную структуру и нам необходимо считать, например, из файла отдельную секцию конфигурации и предоставить ей в какой-то обработчик.

