在软件开发过程中,配置文件是必不可少的一部分,它们通常包含了应用程序运行时所需的各种设置。然而,当配置文件结构变得复杂,或者包含嵌套子节时,读取这些配置可能会变得相当繁琐。为了解决这个问题,开发了一个名为“配置文件解析器”的工具,它旨在简化从配置文件中读取数据的过程。
这个库可以通过NuGet获取,或者也可以从GitHub上获取源代码。
假设程序需要连接到多个外部系统和数据库,并且能够向系统管理员发送电子邮件。决定将这些设置放入三个不同的部分。
以下是XML配置文件的一个示例:
<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
public class ExternalSystemSettings
{
public AuthenticationServiceSettings AuthenticationSettings { get; set; }
public StaffServiceSettings StaffSettings { get; set; }
}
public class AuthenticationServiceSettings
{
public string Login { get; set; }
public string Token { get; set; }
public List<string> Urls { get; set; }
}
public class StaffServiceSettings
{
public Guid Token { get; set; }
public string Url { get; set; }
}
#endregion
#region DatabasesSettings
public class DatabasesSettings
{
public MongoDatabaseSettings MongoSettings { get; set; }
public Dictionary<string, SqlSettings> SqlSettings { get; set; }
}
public class MongoDatabaseSettings
{
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}
public class SqlSettings
{
public string ConnectionString { get; set; }
}
#endregion
#region Smtp
public class SmtpSettings
{
public string Host { get; set; }
public string Sender { get; set; }
[CustomStrategy(typeof(SplitRecipientsCustomStrategy))]
public List<string> Recipients { get; set; }
}
#endregion
在配置文件中,需要声明将使用配置文件解析器。
<?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 = (ExternalSystemSettings)(dynamic)ConfigurationManager.GetSection("ExternalSystemSettings");
或者
ExternalSystemSettings externalSystemSettings = (dynamic)ConfigurationManager.GetSection("ExternalSystemSettings");
执行这段代码后,将有两个对象包含设置。可能会注意到目前没有获取SmtpSettings。这是为了展示工具的额外能力。
在不同的项目中,可能需要在配置文件中有不同的设置,并有自己的逻辑来处理它们。这个工具的设计方式允许通过添加新策略来轻松扩展它,以覆盖所有需要的场景。
例如,让看看Recipients部分:
<Recipients>
clien1@gmail.com;clien2@gmail.com;clien3@gmail.com
</Recipients>
这个部分包含了一个由分号分隔的电子邮件地址列表。根据要求,需要将每个电子邮件作为一个单独的元素添加到数组中。为了实现这一点,创建了SplitRecipientsCustomStrategy类并实现了ICustomMappingStrategy接口。
public class SplitRecipientsCustomStrategy : 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);
}
}
在这个类中,实现了一个算法,根据任务要求从部分解析值。注意,如果值是从属性中读取的,则调用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");