将 app.config 设置移动到 db 并使用值类型动态设置 return 数据类型

Moving app.config settings to db and using value type to dynamically set the return data type

我有一个 windows 服务应用程序,我想从 asp.net 站点管理它的设置。随着我的应用程序的增长,我在 app.config 文件中的设置列表也在增长。因此,我决定将这些设置移动到我的 SQL 数据库中的 table,以便能够跟踪它们并为我提供一种从管理站点修改设置的方法。我 运行 遇到一个问题,我试图将设置值类型存储在 table 中,然后使用它将值 属性 更改为存储的类型。例如,我定义了很多 TimeSpan。在 SQL table 中,数据将如下所示。

guid    settingName     settingValue    settingType
936767f5-63b5-4844-9991-29f6f92c53f2    SMTimeStart    12:00:00    TimeSpan

我正在尝试使用以下代码提取设置并return它的类型正确。

    public class SettingDataValue
    {
        public Guid guid { get; set; }
        public string SettingName { get; set; }
        public string SettingValue { get; set; }
        public string SettingType { get; set; }


    }
    public static dynamic getSettingFromDB(string name)
    {
        SettingDataValue s = new SettingDataValue();
        using (IDbConnection _db = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString), commandTimeout = null)
        {
            s = _db.Query<SettingDataValue>("Select Guid, SettingName, SettingValue ,SettingType from SiteSettings where settingName = '" + name + "'").SingleOrDefault();
        }
        PropertyInfo propertyInfo = s.GetType().GetProperty(s.SettingType);
        propertyInfo.SetValue(s, Convert.ChangeType(s.SettingValue, propertyInfo.PropertyType), null);

        return s.SettingValue;
    }

然而,当我 运行 这个时,我在

上得到一个空引用异常
propertyInfo.SetValue(s, Convert.ChangeType(s.SettingValue, propertyInfo.PropertyType), null);

当我测试查询并使用 sql 分析器观察时,我知道该查询有效。有什么想法或建议吗?

您遇到的问题不是您没有取回数据,而是 PropertyInfo 为空。

行:

PropertyInfo propertyInfo = s.GetType().GetProperty(s.SettingType);

实际上是在尝试在 SettingDataValue 对象上找到 属性 "TimeSpan"(使用您提供的数据行)。由于此 属性 不存在,因此 returning null。然后您尝试设置 属性 的值并获取空引用异常。

我认为您要做的是将字符串值转换为设置类型中的值类型。您不需要为此使用反射。我建议向您的 SettingDataValue 对象添加只读 属性:

public object Value
{
    get
    {
        return SomeMethodThatConvertsYourStringValueToTarget();
    }
}

然后是真正进行转换的私有方法。

private object SomeMethodThatConvertsYourStringValueToTarget();
{
    switch (SettingType)
    {
        case "TimeSpan":
            //conversion code
            break;
    }
}

然后将您的 getSettingsFromDb 方法更改为 return 对象而不是动态的。然后你可以像这样使用它:

TimeSpan ts = (TimeSpan)getSettingsFromDb("SMTimeStart");

或者,您可以为每种数据类型创建一个方法,这样您在使用它时就不必区分大小写了。所以你可以像这样使用它:

TimeSpan ts = getTimeStampFromDb("SMTimeStart");

所以有几件事我错了。正如 David 提到的,我不需要使用反射来获取类型。相反,我需要使用 Type.GetType 方法来解析文本。第二件事是数据类型必须是与它们一起记录的名称空间。

这是现在可用的更新代码。

    public class SettingDataValue
    {
        public Guid guid { get; set; }
        public string SettingName { get; set; }
        public string SettingValue { get; set; }
        public string SettingType { get; set; }

    }
    public static dynamic getSettingFromDB(string name)
    {

        SettingDataValue s = new SettingDataValue();
        using (IDbConnection _db = new SqlConnection(ConfigurationManager.ConnectionStrings["NetworkCafeConnectionString"].ConnectionString))
        {
            s = _db.Query<SettingDataValue>("Select guid, SettingName, SettingValue ,SettingType from SiteSettings where SettingName = '" + name + "'").FirstOrDefault();
        }
        Type type = Type.GetType(s.SettingType);
        var converter = TypeDescriptor.GetConverter(type);
        return converter.ConvertFrom(s.SettingValue);
    }

这是 sql table.

中的数据示例
guid        SettingName            SettingValue    SettingType
95473a84    SMCreateTime           00:12:00        System.TimeSpan
81037bdc    SMCreateEnabled        True            System.Boolean
99e06df7    SMUsername             Username        System.String