Содержание
Когда мы работаем с файловыми провайдерами конфигурации, то настройки в таких файлах могут иметь достаточно разветвленную структуру. В результате, читать такие настройки по одной становится крайне неудобно. Платформа 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#. Такой подход удобно использовать, когда конфигурация имеет сложную структуру и нам необходимо считать, например, из файла отдельную секцию конфигурации и предоставить ей в какой-то обработчик.