- PVSM.RU - https://www.pvsm.ru -
В данной статье мне бы хотелось рассмотреть проблему загрузки настроек из конфигурационных файлов. Как правило, разработчики используют тяжеловесное и сложное API из пространства имен System.Configuration и считывают настройки шаг за шагом. В случае если в конфигурационном файле секция, которую надо считать, представляет из себя простую структуру (без вложенностей), то, в принципе, считывание не вызывает особых проблем. Однако, как только конфигурация усложняется и/или появляются вложенные подсекции, то распарсивание превращается в настоящую головную боль. Для простого и быстрого считывания настроек и загрузку их в память отлично подойдет библиотека ConfigurationParser, которая возьмет на себя все сложности работы с конфигурационными файлами.
Данная библиотека доступна для скачивания через NuGet [1]. Или вы можете скачать исходники из GitHub [2].
Для демонстрации возможностей библиотеки давайте представим, что нашей программе требуются настройки для подключения к нескольким внешним сервисам, базам данных и наша система должна уметь отправлять письма администраторам системы. Мы решили, что данные настройки будут находится в трех секциях.
<ExternalSystemSettings>
<AuthenticationSettings>
<Login>DotNetCraft</Login>
<Token>qwerty</Token>
<Urls>
<Url>https://github.com/DotNetCraft/ConfigurationParser</Url>
<Url>https://github.com/DotNetCraft/ConfigurationParser</Url>
</Urls>
</AuthenticationSettings>
<StaffSettings Token="{D0C148F7-83C0-41B0-8F18-B47CAB09AD99}" Url="https://github.com/DotNetCraft/ConfigurationParser"/>
</ExternalSystemSettings>
<DatabasesSettings>
<MongoSettings ConnectionString="mongo.url" DatabaseName="DotNetCraft"/>
<SqlSettings>
<item key="TenantA">
<value>
<SqlSettings ConnectionString="sql.TenantA.com"/>
</value>
</item>
<item>
<key>TenantB</key>
<value>
<SqlSettings>
<ConnectionString>sql.TenantB.com</ConnectionString>
</SqlSettings>
</value>
</item>
</SqlSettings>
</DatabasesSettings>
<SmtpSettings Host="gmail.com" Sender="no-reply">
<Recipients>clien1@gmail.com;clien2@gmail.com;clien3@gmail.com</Recipients>
</SmtpSettings>
Следующим шагом необходимо создать классы, в которых мы будем хранить настройки системы.
#region ExternalSystemSettings
class ExternalSystemSettings
{
public AuthenticationServiceSettings AuthenticationSettings { get; set; }
public StaffServiceSettings StaffSettings { get; set; }
}
class AuthenticationServiceSettings
{
public string Login { get; set; }
public string Token { get; set; }
public List<string> Urls { get; set; }
}
class StaffServiceSettings
{
public Guid Token { get; set; }
public string Url { get; set; }
}
#endregion
#region DatabasesSettings
class DatabasesSettings
{
public MongoDatabaseSettings MongoSettings { get; set; }
public Dictionary<string, SqlSettings> SqlSettings { get; set; }
}
class MongoDatabaseSettings
{
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}
class SqlSettings
{
public string ConnectionString { get; set; }
}
#endregion
#region Smtp
class SmtpSettings
{
public string Host { get; set; }
public string Sender { get; set; }
[CustomStrategy(typeof(SplitRecipientsCustomStrategy))]
public List<string> Recipients { get; set; }
}
#endregion
В конфигурационном файле нам необходимо объявить, что мы будем использовать ConfigurationParser.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="ExternalSystemSettings" type="DotNetCraft.ConfigurationParser.SimpleConfigurationSectionHandler, DotNetCraft.ConfigurationParser" />
<section name="DatabasesSettings" type="DotNetCraft.ConfigurationParser.SimpleConfigurationSectionHandler, DotNetCraft.ConfigurationParser" />
<section name="SmtpSettings" type="DotNetCraft.ConfigurationParser.SimpleConfigurationSectionHandler, DotNetCraft.ConfigurationParser" />
</configSections>
…
</configuration>
Теперь мы можем считать нашу конфигурацию легко и непринужденно:
ExternalSystemSettings externalSystemSettings = (dynamic)ConfigurationManager.GetSection("ExternalSystemSettings");
DatabasesSettings databasesSettings = (dynamic)ConfigurationManager.GetSection("DatabasesSettings");
После выполнения кода у нас будет создано 2 объекта, которые и будут содержать наши настройки. Как вы можете справедливо заметить, мы не считываем SmtpSettings. Это сделано для того, чтобы продемонстрировать дополнительные возможности утилиты.
В различных проектах вам может понадобиться записывать разнообразные настройки в конфигурационные файлы и иметь свою логику как с ними работать. Утилита спроектирована таким образом, что вы можете ее легко расширить путем добавления новой стратегии и покрыть все сценарии, которые вам нужны. Для примера, давайте рассмотрим секцию Recipients:
<Recipients>clien1@gmail.com;clien2@gmail.com;clien3@gmail.com</Recipients>
Эта секция содержит список email-ов, разделенных точкой с запятой. Согласно нашему ТЗ и классу мы должны записать каждый адрес как отдельный элемент в массиве. Для выполнения поставленной задачи нам надо создать класс SplitRecipientsCustomStrategy и реализовать интерфейс ICustomMappingStrategy
class SplitRecipientsCustomStrategy : ICustomMappingStrategy
{
#region Implementation of ICustomMappingStrategy
public object Map(string input, Type itemType)
{
string[] items = input.Split(';');
List<string> result = new List<string>();
result.AddRange(items);
return result;
}
public object Map(XmlNode xmlNode, Type itemType)
{
string input = xmlNode.InnerText;
return Map(input, itemType);
}
#endregion
}
Внутри нам необходимо реализовать алгоритм распарсивания значения из секции в соответствии с нашим заданием. Необходимо учитывать, что метод Map(string input, Type itemType) вызывается если значение прочитано из атрибута, а метод Map(XmlNode xmlNode, Type itemType) вызывается если значение прочитано из секции. Согласно конфигурационному файлу, значение будет прочитано из секции.
После этого нам необходимо пометить свойство Recipients атрибутом CustomStrategy в котором нужно указать, что за «стратегия» будет использоваться для данного поля:
[CustomStrategy(typeof(SplitRecipientsCustomStrategy))]
public List<string> Recipients { get; set; }
Вот и все, теперь мы можем считать настройки электронной почты.
SmtpSettings smtpSettings = (dynamic)ConfigurationManager.GetSection("SmtpSettings");
Как вы видите, ConfigurationParser делает работу по чтению настроек из конфигурационного файла очень удобной и сохраняет кучу времени. При этом она легко расширяется благодаря подключению новых стратегий.
Если у вас возникнут какие-либо вопросы или предложения, пожалуйста, пишите их в комментариях, я с радостью на них отвечу.
Автор: DotNetCraft
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/net/250848
Ссылки в тексте:
[1] NuGet: https://www.nuget.org/packages/DotNetCraft.ConfigurationParser
[2] GitHub: https://github.com/DotNetCraft/ConfigurationParser
[3] Источник: https://habrahabr.ru/post/324868/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox
Нажмите здесь для печати.