将魔法字符串替换为其他东西-具有层次结构支持
本文关键字:-具 层次结构 支持 其他 字符串 替换 | 更新日期: 2023-09-27 18:18:05
我想存储程序配置,我不想绑定任何实现(无论是XML还是ADO.NET)。配置本身在本质上是分层的。例如,它包含:
- 数据库主机名 <
- 数据库端口/gh>
- 数据库用户
- 打开/关闭X支持
- 打开/关闭Y支持
- Z 参数
到目前为止,我已经创建了字符串到对象的字典,如:
var config = new Dictionary<string, string>();
config["database/host"] = "localhost";
config["database/port"] = "port";
然而,这是一件坏事,因为很难跟踪哪个模块使用了哪个键,而且很难重构。而且很明显它不是分层的
所以…我想用别的东西替换我的魔法字符串映射。我想知道解决方案:
- 支持层次结构,所以很容易看到数据是如何结构的,
- 不使用魔法字符串, 尽量少用样板文件。
假设配置管理器是平面的,即它看起来像这样:
interface IConfigurationManager
{
void Get(ConfigurationKey key);
void Set(ConfigurationKey key, string value);
}
public class ConfigurationKey
{
public ConfigurationKey(string name)
{
Name = name;
}
public string Name { get; private set; }
}
我想到了这个方法:
public static class ConfigurationKeys
{
public static class Root
{
public static class Database
{
public static ConfigurationKey Host;
public static ConfigurationKey Port;
public static ConfigurationKey User;
}
public static class X
{
public static ConfigurationKey Enabled;
}
public static class Y
{
public static ConfigurationKey Enabled;
}
}
public static void Build()
{
Build(typeof (ConfigurationKeys));
}
private static void Build(Type type)
{
var configurationKeyFields = type
.GetFields()
.Where(field => field.FieldType == typeof (ConfigurationKey));
foreach (FieldInfo field in configurationKeyFields)
field.SetValue(null, CreateConfigurationKey(type, field));
var nestedClasses = type.GetNestedTypes().Where(nestedType => nestedType.IsClass);
foreach (Type nestedClass in nestedClasses)
Build(nestedClass.UnderlyingSystemType);
}
private static ConfigurationKey CreateConfigurationKey(Type type, FieldInfo field)
{
var parentPath = type.FullName.Substring(typeof (Root).FullName.Length + 1).Replace("+", "/");
return new ConfigurationKey(parentPath + "/" + field.Name);
}
}
现在很容易通过以下方式访问它:
ConfigurationKeys.Build();
var cm = new ConfigurationManager();
cm.Set(ConfigurationKeys.Root.Database.Host, "localhost");
ConfigurationKeys.Root.Database.Host // == "Database/Host"
优点:
- 读
- 易于重构
- 几乎没有样板
- 嵌套,从而成功地描绘现实和智能感知友好
缺点:
- 由于静态类和嵌套类型,几乎不可能在测试中模拟
- 很难移植到其他语言,因为它依赖于反射的使用
- 对
Build()
等方法的伪调用;不幸的是,它不能被静态构造函数取代,因为访问嵌套类型不会触发父静态构造函数,并且为每个嵌套类型提供静态构造函数会增加样板文件