⚙️ Cпособы .NET конфигурации – IConfiguration

Каждое приложение имеет несколько источников хранения настроек. Обсудим с вами, как читать данные из разных источников, группировать их для использования внутри приложения и как разбираться в конфигурации.

IConfiguration

IConfiguration — это набор свойств конфигурации приложения в виде пар «ключ — значение». Интерфейс IConfiguration может быть реализован для чтения из разных источников данных.

Конфигурация происходит путем указания, из каких источников стоит читать данные. При этом каждый поставщик конфигурации добавляет «слой» значений к ConfigurationBuilder. Метод Build() прочтет конфигурацию из указанного списка источников. Причем последовательность указания источников данных имеет значение. Каждый последующий источник переопределяет значение с таким же ключом, которое было в предыдущем источнике.

Для определения списка источников данных используется класс ConfigurationBuilder. Метод Build() прочтет данные и вернет объект IConfiguration, через который осуществляется доступ к данным.

При запуске приложения необходимо настроить чтение данных из разных источников. По умолчанию присутствует поддержка JSON, environments, CLI arguments и другие.

Например, указан такой порядок: AddJsonFile, затем AddEnvironmentsVariables, то вначале будут прочитаны данные из JSON-файла, а затем — переменных окружения. Если в переменной окружения есть какое-либо значение, то информация JSON-файла по ключу будет перезаписана. Метод Build() при этом возвращает IСonfiguration объект, который впоследствии можно использовать для чтения данных.

Непосредственно для чтения данных используем следующий код:

public class MySettings
{
    public string AppName { get; set; }
    public int Port { get; set; }
    public string Host { get; set; }
}

// десериализовать всю секцию
var settings = configuration.GetRequiredSection("MySettings").Get<MySettings>();

// получить отдельное значение
var port = configuration.GetValue<int>("MySettings:Port");

// строку
var host = configuration["MySettings:Host"];

Что делать, если источник не стандартный?

Если ни один из доступных поставщиков данных вам не подходит, покажем, как реализовать настраиваемого поставщика данных. Например, использовать вашу базу данных или данные из объекта как источник конфигурации.

Создадим собственное расширение для чтения конфигурации. Специальный поставщик для чтения параметров из предоставленного Dictionary объекта.

  • Provider (чтение/запись данных)
public class DictionaryConfigurationProvider : ConfigurationProvider
{
    private readonly IDictionary<string, string> _data;

    public DictionaryConfigurationProvider(IDictionary<string, string> data)
        => _data = data;
    
    public override void Load() => Data = _data;
}
  • Source (интеграция Provider и Builder)
public class DictionaryConfigurationSource : IConfigurationSource
{
    private readonly IDictionary<string, string> _data;

    public DictionaryConfigurationSource(IDictionary<string, string> data) 
        => _data = data;
    
    public IConfigurationProvider Build(IConfigurationBuilder builder) 
        => new DictionaryConfigurationProvider(_data);
}
  • Расширение для IConfigurationBuilder
public static class ConfigurationBuilderExtensions
{
    public static IConfigurationBuilder AddSimpleConfiguration(
    
    this IConfigurationBuilder builder, IDictionary<string, string> data)
    {
        data ??= new Dictionary<string, string>();
        return builder.Add(new DictionaryConfigurationSource(data));
    }
}
  • И последний шаг
var data = new Dictionary<string, string>
{
{ "Hello", "World" }
};

var configuration = new ConfigurationBuilder()
    .AddSimpleConfiguration(data)
    .Build();

var who = configuration["Hello"];
Console.WriteLine($"Hello, {who}");

// ---
// Expected Result -> Hello, World

Продвинутая конфигурация для использования в тестах

Для проведения интеграционных или функциональных тестов часто приходится использовать реальное подключение к базе данных. Для этого подходит IConfiguration — делаем подстановку переменных (через environment variables) без необходимости сохранять данные в репозитории приложения.

Модульные тесты в Visual Studio можно настраивать с помощью файла .runsettings. Например, вы можете изменить версию .NET, на которой выполняются тесты, каталог для результатов тестирования или данные, которые собираются во время выполнения теста. Обычно файл .runsettings используется для настройки анализа покрытия кода.

Файлы параметров запуска можно использовать для настройки тестов, запускаемых из командной строки, из среды IDE или в рабочем процессе сборки с помощью Azure Test Plans или Team Foundation Server (TFS).

Файлы настроек запуска необязательны. Если вам не требуется особая конфигурация, вам также не нужен файл .runsettings.

  • Для использования продвинутой конфигурации в тестах создаем локальный файл .runsettings. Тут будет указана переменная окружения DB_CONNECTION_STRING, которая может быть прочитана при запусках тестов.
<?xml version="1.0" encoding="utf-8"?>
<!-- File name extension must be .runsettings -->
<RunSettings>
    <RunConfiguration>
        <EnvironmentVariables>
            <DB_CONNECTION_STRING>
                Server=server;Database=db;Port=5432;UserId=user;Password=pass;
            </DB_CONNECTION_STRING>
        </EnvironmentVariables>
    </RunConfiguration>
</RunSettings>
  • Создаем путь к файлу через csproj

$(MSBuildProjectDirectory)\example.runsettings ...

  • ИЛИ указываем в IDE (в примере Rider)

Использование в тестах

private const string DB_CS_ENV = "DB_CONNECTION_STRING";
private PostgresConnection _connection;

[OneTimeSetUp]
public void Setup()
{
    var config = new ConfigurationBuilder()
        .AddEnvironmentVariables()
        .Build();
    _connection = new PostgresConnection(config.GetSection(DB_CS_ENV).Value);
}

/*
HERE LOGIC FOR TESTS
...
*/

В качестве заключения

В заключение можно сказать, что конфигурирование в .NET является важным инструментом для администрирования и настройки приложений. С помощью конфигурационных файлов можно настраивать различные параметры приложения, такие как подключение к базе данных, настройки безопасности и т. д. Также существует возможность использовать различные способы конфигурирования: конфигурационные файлы или переменные окружения.

Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека шарписта»

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

matyushkin
18 марта 2020

ТОП-10 книг по C#: от новичка до профессионала

Отобрали актуальные книги по C#, .NET, Unity c лучшими оценками. Расположил...
Библиотека программиста
25 августа 2019

Почему C# программисты скоро будут нарасхват

C# программисты становятся более востребованными благодаря развивающейся эк...
Библиотека программиста
12 марта 2018

Видеокурс по C# с нуля: от основ до полноценного приложения

Подробный видеокурс для изучающих C# с нуля. Пройдем путь от основ до напис...