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

本文关键字:配置 程序 我的 泛型 我应该 | 更新日期: 2023-09-27 18:10:24

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

我设想的设置将是字符串、整型或双精度,并将由名称

标识。

设置是通过类实现的:

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

我走的方向对吗?

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

使用转换。ChangeType

return (T)Convert.ChangeType(value, typeof(T));

我有一个模糊类似的变量提供程序接口,其中我没有使用泛型。我从泛型开始,发现它并没有提高代码的可读性或性能,特别是因为类型很少,而且从一开始就知道。毕竟,您没有得到任何动态的东西,它是从您给出的默认值推断类型的。我还希望我的变量提供程序可以在不提供默认值的情况下使用,并且不想为此使用不同的语法。

所以我的包含两个层次。一个是我在代码中使用的公共接口提供程序,它可以在以下示例中使用:

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["answerswer"];
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()并返回它。

最终,你可以这样做。如果您使用这样的泛型,然后希望使用它而不使用默认值,则必须使用不同的语法来指定类型。