Создаем собственный провайдер конфигурации в ASP.NET Core
ASP.NET Core использует новую модель конфигурирования на основе IOptions<>, о чем я писал ранее. Эта модель позволяет считывать конфигурационные параметры отдельными частями приложения. Но где эти данные размещены? Давайте разберемся с этим вопросом.
Startup.cs
Для начала заглянем в файл Startup.cs — файл, с которого начинается запуск приложения. В стандартном шаблоне проекта ASP.NET Core, в конструкторе класса Startup создается объект ConfigurationBuilder и на его основе строится объект с конфигурационными данными. Этот объект сохраняется в локальное свойство и фактически хранит словарь конфигурационных параметров.
public class Startup
{
public Startup(IHostingEnvironment env)
{
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", true, true);
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
Внутри класса Startup это свойство затем неоднократно используется для настройки отдельных частей приложения — об этом я писал в предыдущей записи.
Источники данных для конфигурации
Из кода Startup.cs можно понять, что ConfigurationBuilder‘у передается файл appsettings.json, в котором и хранятся настройки приложения. Чем хорош механизм конфигурирования ASP.NET Core — это возможностью использовать одновременно несколько источников данных для конфигурации. Например, можно хранить конфигурацию в нескольких JSON-файлах:
public Startup(IHostingEnvironment env)
{
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile("another-settings.json", true, true);
Можно также использовать разные типы источников. Например, часть конфигурации хранить в JSON, а другую — в XML:
public Startup(IHostingEnvironment env)
{
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddXmlFile("appsettings.xml", true, true);
Из коробки ASP.NET Core предлагает несколько различных способов задания источников конфигурации:
EnvironmentVariables— извлекает конфигурационные параметры из переменных окружения операционной системыJSON,XML,Ini— позволяет использовать файлы JSON, XML и INI для хранения конфигруационных параметровUserSecrets— позволяет использовать специальное защищенное хранилище для хранения конфигурационных параметров
Базовый набор позволяет организовать гибкую систему конфигурации приложения ASP.NET Core. Но по-настоящему мощным этот инструмент становится за счет возможности его расширения. Другими словами, вы можете создать собственный источник данных для конфигурации приложения и использовать его вместе со встроенными механизмами.
Собственный источник конфигурации ASP.NET Core
В качестве учебного примера, создадим источник данных, позволяющий хранить конфигурацию в файлах формата YAML.
Реализация собственного источника конфигурации начинается с создания класса, реализующего интерфейс IConfigurationSource:
public class YamlConfigurationSource : IConfigurationSource
{
public YamlConfigurationSource(string fileName)
{
FileName = fileName;
}
public string FileName { get; }
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new YamlConfigurationProvider(this);
}
}
Основная задача этого класса заключается в получении исходных данных (например, имени конфигруационного файла) и создании объекта ConfigurationProvider для данного источника. Реализацией провайдера займемся чуть позже, а пока давайте сразу добавим методы расширения, чтобы можно было удобно использовать этот источник данных в Startup.cs:
public static class YamlConfigurationSourceExtensions
{
public static IConfigurationBuilder AddYamlFile(
this IConfigurationBuilder builder, string filename)
{
return builder.Add(new YamlConfigurationSource(filename));
}
}
Для реализации провайдера нам потребуется доступ к файловой системе. Поэтому при создании провайдера передадим ссылку на него. Код YamlConfigurationSource изменится следующим образом:
public class YamlConfigurationSource : IConfigurationSource
{
public YamlConfigurationSource(string fileName)
{
FileName = fileName;
}
public string FileName { get; }
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new YamlConfigurationProvider(this, builder.GetFileProvider());
}
}
Осталось реализовать провайдер для доступа к Yaml. Для этого создадим класс-наследник ConfigurationProvider. Для загрузки данных из источника следует реализовать метод Load:
public class YamlConfigurationProvider : ConfigurationProvider
{
private readonly IFileProvider _fileProvider;
private readonly YamlConfigurationSource _source;
public YamlConfigurationProvider(YamlConfigurationSource source, IFileProvider fileProvider)
{
_source = source;
_fileProvider = fileProvider;
}
public override void Load()
{
}
}
Для работы с Yaml-файлами воспользуемся библиотекой YamlDotNet. Вся суть конфигурационного провайдера сводится к считыванию источника и сохранении конфигурационных значений в служебном словаре, доступном через свойство Data.
public class YamlConfigurationProvider : ConfigurationProvider
{
private readonly IFileProvider _fileProvider;
private readonly YamlConfigurationSource _source;
public YamlConfigurationProvider(YamlConfigurationSource source, IFileProvider fileProvider)
{
_source = source;
_fileProvider = fileProvider;
}
public override void Load()
{
IFileInfo file = _fileProvider.GetFileInfo(_source.FileName);
using (Stream stream = file.CreateReadStream())
{
using (TextReader reader = new StreamReader(stream))
{
Dictionary<object, object> document = new DeserializerBuilder()
.Build()
.Deserialize(reader) as Dictionary<object, object>;
if (document != null)
{
foreach (KeyValuePair<object, object> item in document)
{
Data[item.Key.ToString()] = item.Value.ToString();
}
}
}
}
}
}
Провайдер готов. Осталось подключить его к приложению в Startup.cs:
public class Startup
{
public Startup(IHostingEnvironment env)
{
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddYamlFile("config.yml");
Configuration = builder.Build();
}
Заключение
Приведенный выше пример показывает как за несколько минут можно добавить собственный конфигурационный провайдер в приложение ASP.NET Core.
Обратите внимание, что этот пример годится только для учебных целей. Например, в нем не реализована обработка вложенных свойств YAML. Кроме того, для реализации конфигурационных источников, которые хранят свои данные в файлах существует ещё одна абстракция - FileConfigurationProvider и FileConfigurationSource. Кроме всего прочего в них реализована возможность отслеживания изменений в конфигурационных файлах. Поэтому, если ваш источник конфигурации использует файлы, то собственный провайдер лучше создавать на основе FileConfigurationProvider.
Добавить комментарий