Получать доступ в приложении к настройками через ключи вида AppSettings:Versions:0:Number не очень удобно и надёжно. Для решения этой проблемы существует механизм переноса (маппинга/биндинга) конфигурации на объекты в коде.
Давайте попробуем воспользоваться им:
В папке с нашими уроками введите команду:
dotnet new console -o lesson09
Заменим код Program.cs на:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using var host = Host.CreateDefaultBuilder(args).Build();
var config = host.Services.GetService(typeof(IConfiguration)) as IConfiguration;
var settings = new AppSettings();
config!.GetSection(nameof(AppSettings)).Bind(settings);
Console.WriteLine($"{settings.FirstWord} {settings.SecondWord} {settings.Versions[0].Number}");
Добавим файл AppSettings.cs:
public class AppSettings
{
public string? FirstWord { get; set; }
public string? SecondWord { get; set; }
public class Version
{
public int Number { get; set; }
}
public List<Version> Versions { get; set; } = new();
}
Создайте новый файл appsettings.json в том же каталоге, что и ваш файл Program.cs.
{
"AppSettings": {
"FirstWord": "Hello",
"SecondWord": "dotnet",
"Versions": [
{
"Number": 7
}
]
}
}
Создайте новый файл appsettings.Development.json в том же каталоге, что и ваш файл Program.cs.
{
"AppSettings": {
"Versions": [
{
"Number": 8
}
]
}
}
В консоле перейдите в папку с проектом.
Установим зависимость через dotnet cli:
dotnet add package Microsoft.Extensions.Hosting --version 7.0.1
Добавление пакетов отразится в файле lesson09.csproj
Вместо имени файла укажите шаблон appsettings*.json в csproj, все файлы подходящие под него будут копироваться в директорию при сборке проекта. Давайте добавим нужную настройку в lesson09.csproj.
<ItemGroup>
<Content Include="appsettings*.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
Должно получиться следующее:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
</ItemGroup>
<ItemGroup>
<Content Include="appsettings*.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
В этом уроке мы описываем класс конфигурации и маппим (биндим) его на настройки конфигурацию приложения, затем используем получившийся инстанс класса в приложении для использования параметров конфигурации в приложении. На что тут стоит обратить внимание:
Модификатор доступа public - указывает откуда будет доступен класс, говорит, что класс доступен всем.
<aside>
🐩 Подробней про public можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/public.
</aside>
Класс Version вложен в класс AppSettings. Так сделано по двум причинам: 1 - Version это часть класса AppSettings (доступ до него получился AppSettings.Version); 2 - размещать в одном файле два на одном уровне является не рекомендуемой практикой, а делать два файла и разносить фактически один объект в разные места не удобно в поддержке (к слову если бы AppSettings.Version находится в отдельном файле он бы назывался AppSettingsVersion).
<aside> 🐩 Подробней про вложенные типы можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/nested-types.
</aside>
Ключевое слово class - говорит о том, что описываем тип является изменяемым ссылочным типом.
<aside>
🐩 Подробней про class можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/csharp/fundamentals/types/classes.
</aside>
Оператор ? говорит о том, что значение допускает null, фактически делает тип ссылочным оборачивая его в контейнер System.Nullable<T>.
<aside>
🐩 Подробней про class можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/builtin-types/nullable-value-types.
</aside>
Ключевые слова get и set говорят о том, что поле является акцессором позволяющим как получать значение поля так и менять его.
<aside>
🐩 Подробней про get и set можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/using-properties.
</aside>
Ключевое слово int является псевдонимом структуры Int32, говорит о том, что является типом значения, 32х битным целы числом, имеющее максимально возможное допустимое значение равное 2 147 483 647.
<aside> 🐩 Подробней про структуры можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/builtin-types/struct.
</aside>
<aside> 🐩 Подробней про целочисленные типы можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/builtin-types/integral-numeric-types.
</aside>
<aside>
🐩 Подробней про int можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/api/system.int32?view=net-7.0.
</aside>
Универсальный (дженерик) класс List<T> это класс динамического списка, позволяющий задать какой именно тип хранится в элементах этого списка.
<aside> 🐩 Подробней про универсальные типы можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/csharp/fundamentals/types/generics.
</aside>
<aside>
🐩 Подробней про List<T> можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/api/system.collections.generic.list-1?view=net-7.0.
</aside>
Выражение new в вариантах new AppSettings() и new() - конструируют новый экземпляр класса, в первом случае конструируемый класс задаётся явно, во втором вычисляется из левой части выражения.
<aside>
🐩 Подробней про new можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/operators/new-operator.
</aside>
Ключевое слово nameof - превращает имя типа переданного в функцию в строковую переменную, пример nameof(MyClass) вернёт строку “MyClass”.
<aside>
🐩 Подробней про nameof можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/operators/nameof.
</aside>