Проекция конфигурации на классы
В .NET Core, проекция конфигурации на классы (Configuration Binding) - это механизм, который позволяет связывать структуру конфигурационных данных (например, из файлов appsettings.json или переменных среды) с классами C#. Это позволяет удобно работать с конфигурационными данными в приложении, избегая прямого обращения к разрозненным источникам конфигурации.
Вот основные шаги по проекции конфигурации на классы в .NET Core:
1. Определение классов для конфигурации:
Создайте классы C#, которые будут соответствовать структуре ваших конфигурационных данных. Например:
public class DatabaseSettings
{
public string ConnectionString { get; set; }
public int TimeoutSeconds { get; set; }
}
public class EmailSettings
{
public string SmtpServer { get; set; }
public int SmtpPort { get; set; }
public string SenderEmail { get; set; }
}
2. Регистрация конфигурации в IConfigurationRoot
:
В методе ConfigureServices()
класса Startup
, зарегистрируйте конфигурационные данные и связанные с ними классы:
public void ConfigureServices(IServiceCollection services)
{
// Связываем конфигурацию с классами
services.Configure<DatabaseSettings>(Configuration.GetSection("DatabaseSettings"));
services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));
// Другие регистрации сервисов
services.AddControllers();
}
3. Использование связанных классов в приложении:
Теперь вы можете внедрять эти классы конфигурации в качестве зависимостей в контроллеры, сервисы или другие компоненты вашего приложения:
public class MyController : ControllerBase
{
private readonly DatabaseSettings _databaseSettings;
private readonly EmailSettings _emailSettings;
public MyController(IOptions<DatabaseSettings> databaseOptions, IOptions<EmailSettings> emailOptions)
{
_databaseSettings = databaseOptions.Value;
_emailSettings = emailOptions.Value;
}
public IActionResult Index()
{
// Использование настроек из связанных классов
var connectionString = _databaseSettings.ConnectionString;
var smtpServer = _emailSettings.SmtpServer;
// Логика контроллера
return View();
}
}
В этом примере контроллер получает доступ к конфигурационным настройкам через внедрение зависимостей IOptions<DatabaseSettings>
и IOptions<EmailSettings>
.
Ключевые преимущества использования проекции конфигурации на классы:
1. Структурированный доступ к конфигурации: Классы C# обеспечивают четкую и структурированную модель для конфигурационных данных, облегчая их использование в приложении.
2. Валидация и типизация: Классы конфигурации позволяют применять валидацию и использовать типизированные значения вместо работы с разрозненными строковыми данными.
3. Injecting Dependencies: Благодаря механизму внедрения зависимостей, конфигурационные классы могут быть легко внедрены в другие компоненты, обеспечивая высокую степень модульности.
4. Переиспользование: Определенные классы конфигурации могут быть повторно использованы в различных частях приложения, улучшая управляемость и согласованность конфигурационных данных.
Второй способ от metanit.com.
Например, определим в проекте новый файл person.json, который будет хранить данные пользователя:
{
"name": "Tom",
"age": "22"
}
Под эти данные определим в проекте класс Person:
public class Person
{
public string Name { get; set; } = "";
public int Age { get; set; } = 0;
}
Теперь свяжем конфигурацию из файла person.json с объектом класса Person:
var builder = WebApplication.CreateBuilder();
var app = builder.Build();
builder.Configuration.AddJsonFile("person.json");
var tom = new Person();
app.Configuration.Bind(tom); // связываем конфигурацию с объектом tom
app.Run(async (context) => await context.Response.WriteAsync($"{tom.Name} - {tom.Age}"));
app.Run();
public class Person
{
public string Name { get; set; } = "";
public int Age { get; set; } = 0;
}
Ключевой момент заключается в применении метода Bind:
var tom = new Person();
app.Configuration.Bind(tom);
Для объекта IConfiguration определен метод Bind(), который в качестве параметра принимает объект, который надо связать с данными. Стоит отметить, что между конфигурацией в json и классом Person имеется соответствие по названию свойств, благодаря чему может осуществляться связка (регистр в данном случае роли не играет).
В качестве альтернативы методу Bind мы могли бы использовать метод Get<T>(), который возвращает объект созданного класса:
Person tom = app.Configuration.Get<Person>();
В этом случае нам не надо предварительно создавать объект класса Person.
Подобным образом можно выполнять привязку при получении конфигурации через механизм Dependency Injection:
var builder = WebApplication.CreateBuilder();
var app = builder.Build();
builder.Configuration.AddJsonFile("person.json");
app.Map("/", (IConfiguration appConfig) =>
{
var tom = appConfig.Get<Person>(); // связываем конфигурацию с объектом tom
return $"{tom.Name} - {tom.Age}";
});
app.Run();
public class Person
{
public string Name { get; set; } = "";
public int Age { get; set; } = 0;
}
Привязка сложных объектов
Рассмотрим привязку более сложных по структуре данных. Определим следующий файл person.json:
{
"age": "28",
"name": "Tom",
"languages": [
"English",
"German",
"Spanish"
],
"company": {
"title": "Microsoft",
"country": "USA"
}
}
Для представления этих данных в коде C# определим следующие классы:
public class Person
{
public string Name { get; set; } = "";
public int Age { get; set; }
public List<string> Languages { get; set; } = new();
public Company? Company { get; set; }
}
public class Company
{
public string Title { get; set; } = "";
public string Country { get; set; } = "";
}
Теперь выполним в приложении привязку из конфигурации json в объекты классов C#:
var builder = WebApplication.CreateBuilder();
var app = builder.Build();
builder.Configuration.AddJsonFile("person.json");
var tom = new Person();
app.Configuration.Bind(tom);
app.Run(async (context) =>
{
context.Response.ContentType = "text/html; charset=utf-8";
string name = $"<p>Name: {tom.Name}</p>";
string age = $"<p>Age: {tom.Age}</p>";
string company = $"<p>Company: {tom.Company?.Title}</p>";
string langs = "<p>Languages:</p><ul>";
foreach (var lang in tom.Languages)
{
langs += $"<li><p>{lang}</p></li>";
}
langs += "</ul>";
await context.Response.WriteAsync($"{name}{age}{company}{langs}");
});
app.Run();
public class Person
{
public string Name { get; set; } = "";
public int Age { get; set; }
public List<string> Languages { get; set; } = new();
public Company? Company { get; set; }
}
public class Company
{
public string Title { get; set; } = "";
public string Country { get; set; } = "";
}
Привязка конфигурации из xml
Возьмем выше определенные классы Person и Company. И добавим в проект файл person.xml, который будет содержать аналогичные данные:
<?xml version="1.0" encoding="utf-8" ?>
<person>
<name>Tom</name>
<age>35</age>
<languages name="0">English</languages>
<languages name="1">German</languages>
<languages name="2">Chinese</languages>
<company>
<title>Microsoft</title>
<country>USA</country>
</company>
</person>
Обратите внимание на установку в файле xml массивов - они имеют атрибут name, который определяет условный индекс.
Применим конфигурацию из выше определенного файла xml в приложении:
var builder = WebApplication.CreateBuilder();
var app = builder.Build();
builder.Configuration.AddXmlFile("person.xml");
var tom = new Person();
app.Configuration.Bind(tom);
app.Run(async (context) =>
{
context.Response.ContentType = "text/html; charset=utf-8";
string name = $"<p>Name: {tom.Name}</p>";
string age = $"<p>Age: {tom.Age}</p>";
string company = $"<p>Company: {tom.Company?.Title}</p>";
string langs = "<p>Languages:</p><ul>";
foreach (var lang in tom.Languages)
{
langs += $"<li><p>{lang}</p></li>";
}
langs += "</ul>";
await context.Response.WriteAsync($"{name}{age}{company}{langs}");
});
app.Run();
public class Person
{
public string Name { get; set; } = "";
public int Age { get; set; }
public List<string> Languages { get; set; } = new();
public Company? Company { get; set; }
}
public class Company
{
public string Title { get; set; } = "";
public string Country { get; set; } = "";
}
Как можно заметить из кода, меняется только подключение файла с json на xml, а весь остальной код остается прежним.
Привязка секций конфигурации
В примерах выше выполнялась привязка корневого объекта конфигурации, однако также можно осуществлять привязку отдельных секций. Например, выше в файле json и xml была определена секция company, которая хранит компанию пользователя. Выполним привязку отдельно этой секции к объекту класса Company:
var builder = WebApplication.CreateBuilder();
var app = builder.Build();
builder.Configuration.AddJsonFile("person.json");
Company company = app.Configuration.GetSection("company").Get<Company>();
app.Run(async (context) =>
{
await context.Response.WriteAsync($"{company.Title} - {company.Country}");
});
app.Run();
public class Company
{
public string Title { get; set; } = "";
public string Country { get; set; } = "";
}
С помощью метода GetSection()
получаем нужную нам секцию конфигурации и затем также можно вызвать методы Bind или Get и выполнить привязку.
Таким образом, проекция конфигурации на классы является мощным инструментом в .NET Core, позволяющим эффективно работать с конфигурационными данными в рамках приложения.
Только полноправные пользователи могут оставлять комментарии. Аутентифицируйтесь пожалуйста, используя сервисы.