我正在尝试编写一个配置管理器,它可以提供来自不同提供商的配置设置(例如设置文件,环境变量,数据库等)。
我设想设置将是字符串,整数或双精度,并将通过名称识别
通过实现此目的的类提供设置:
public interface IConfigurationManagerProvider
{
T GetSetting<T>(string name);
IEnumerable<ConfigurationSetting> GetKnownSettings();
}
首先,我正在尝试编写一个返回环境变量的提供程序
public class EnvironmentVariableProvider : IConfigurationManagerProvider
{
public T GetSetting<T>(string name)
{
string value = Environment.GetEnvironmentVariable(name);
return value as T;
}
public IEnumerable<ConfigurationSetting> GetKnownSettings()
{
return new List<ConfigurationSetting>
{
new ConfigurationSetting("MY_TRACING", typeof (String)),
};
}
}
然而这不会编译,因为它不能转换为T. 如果我把一个类约束放在那里,这限制了我的字符串
public T GetSetting<T>(string name) where T : class
{
string value = Environment.GetEnvironmentVariable(name);
return value as T;
}
实际上这个提供者只能提供字符串(其他提供者会有所不同)但是我希望代码访问配置设置尽可能干净:
public interface IConfigurationManagerConsumer
{
T GetConfiguration<T>(string name, T systemDefault);
}
并像这样使用:
string tracing = ConfigurationManager.GetConfiguration("MY_TRACING", "Unknown");
或者这个:
int maxUserCount = = ConfigurationManager.GetConfiguration("Max User Count", 10);
或者这个:
double pi = ConfigurationManager.GetConfiguration("PI", 3.14159);
我是朝着正确的方向前进的吗?
答案 0 :(得分:3)
return (T)Convert.ChangeType(value, typeof(T));
答案 1 :(得分:1)
我有一个模糊相似的变量提供程序接口,其中我没有使用泛型。我开始使用泛型,并发现它不会使代码更具可读性或性能,特别是因为类型很少并且从一开始就知道。毕竟,你没有得到任何动态,它是从你给出的默认值推断出类型。我还希望我的变量提供程序可以在不提供默认值的情况下使用,并且不想为此使用不同的语法。
所以我的两个级别。一个是我在代码中使用的公共接口提供程序,可以像这些示例中一样使用:
IVariableProvider var;
// providing default value
double pi = var.Double["pi", 3.14159];
// no default value, also bool is just an int, converted by the IVariableProvider.
bool answer = var.Bool["answer"];
int number = var.Int["number"];
if(var.Str.ContainsKey("text"))
{
string text = var.Str["text"];
...
}
如果需要,我可以为var.Float,var.Long等添加公共接口。
在下面,可以为IVariableProvider
提供不同的“来源”以获取变量。源只显示字符串和整数。它也可以使用其他IVariableProvider
作为源。当我调用var.Double["pi"]
时,它会检查是否有任何来源可以为键“pi”提供字符串变量,然后double.Parse()
并返回它。
最终,你可以这样做。如果您使用这样的泛型,然后想要在没有默认值的情况下使用泛型,则必须使用不同的语法来指定类型。