我有一个Windows服务应用程序,我想管理来自asp.net网站的设置。随着我的应用程序的增长,app.config文件中的设置列表也增长了。所以,我决定将这些设置移动到我的SQLDB中的一个表中,以便能够跟踪它们,并为我提供一种从管理站点修改设置的方法。我遇到了一个问题,我试图在表中存储设置值类型,然后使用它将value属性更改为存储的类型。例如,我定义了很多TimeSpan。在SQL表中,数据看起来像这样。
guid settingName settingValue settingType
936767f5-63b5-4844-9991-29f6f92c53f2 SMTimeStart 12:00:00 TimeSpan
我尝试使用以下代码拉取设置并以正确的类型返回。
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 profiler观察时查询有效。有什么想法或建议吗?
答案 0 :(得分:1)
所以我错了几件事。正如大卫所说,我不需要使用反射来获得类型。相反,我需要使用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表中的数据示例。
guid SettingName SettingValue SettingType
95473a84 SMCreateTime 00:12:00 System.TimeSpan
81037bdc SMCreateEnabled True System.Boolean
99e06df7 SMUsername Username System.String
答案 1 :(得分:0)
您遇到的问题不是您没有收到数据,而是PropertyInfo为空。
该行:
PropertyInfo propertyInfo = s.GetType().GetProperty(s.SettingType);
实际上是尝试在SettingDataValue对象上找到属性“TimeSpan”(使用您提供的数据行)。由于此属性不存在,因此返回null。然后,您尝试设置属性的值并获取空引用异常。
我认为你要做的是将字符串值转换为设置类型中的值类型。你不需要使用反射。我建议在您的SettingDataValue对象中添加只读属性:
public object Value
{
get
{
return SomeMethodThatConvertsYourStringValueToTarget();
}
}
然后是实际进行转换的私有方法。
private object SomeMethodThatConvertsYourStringValueToTarget();
{
switch (SettingType)
{
case "TimeSpan":
//conversion code
break;
}
}
然后更改getSettingsFromDb方法以返回对象而不是动态。然后你就可以使用它:
TimeSpan ts =(TimeSpan)getSettingsFromDb(“SMTimeStart”);
或者,您可以为每种数据类型创建一个方法,这样您在使用它时就不必考虑它。所以你可以使用它:
TimeSpan ts = getTimeStampFromDb(“SMTimeStart”);