我应该使用泛型来简化我的配置提供程序类吗?

时间:2011-10-05 12:02:17

标签: c# generics

我正在尝试编写一个配置管理器,它可以提供来自不同提供商的配置设置(例如设置文件,环境变量,数据库等)。

我设想设置将是字符串,整数或双精度,并将通过名称识别

通过实现此目的的类提供设置:

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);

我是朝着正确的方向前进的吗?

2 个答案:

答案 0 :(得分:3)

使用Convert.ChangeType

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()并返回它。

最终,你可以这样做。如果您使用这样的泛型,然后想要在没有默认值的情况下使用泛型,则必须使用不同的语法来指定类型。