题
我目前正在处理一个应用程序,在该应用程序中我需要从SQL数据库加载数据,然后将检索值分配到对象的属性中。我正在使用反射这样做,因为属性名称和列名是相同的。但是,许多属性都使用自定义结构类型,该类型基本上是小数类型的货币包装器。我已经在结构中定义了隐性转换:
public static implicit operator Currency(decimal d)
{
return new Currency(d);
}
当我在代码中使用它时,这很好。但是,当我有这个时:
foreach (PropertyInfo p in props)
{
p.SetValue(this, table.Rows[0][p.Name], null);
}
它引发了一个参数,指出它不能从system.cimal转换为货币。我很困惑,因为在任何其他情况下都可以正常工作。
解决方案
一世 思考 您需要首先解开该值 table.Rows[0][p.Name]
作为一个 decimal
.
换句话说:
foreach (PropertyInfo p in props)
{
if (p.PropertyType == typeof(Currency))
{
Currency c = (decimal)table.Rows[0][p.Name];
p.SetValue(this, c, null);
}
else
{
p.SetValue(this, table.Rows[0][p.Name], null);
}
}
这是我以前见过的问题,所以我实际上决定 写一篇博客文章. 。任何寻求更多解释的人,都可以随意阅读。
其他提示
不幸的是,运行时未使用这些用户定义的转换操作员。它们仅在编译时由编译器使用。因此,如果您采取了强烈的体型 decimal
并将其分配给强大的 Currency
, ,编译器将向您的转换操作员插入一个电话,每个人都很高兴。但是,当您打电话 SetValue
当您在这里做的时候,运行时希望您给它一个适当类型的价值。运行时不知道该转换操作员存在,并且永远不会称呼它。
我认为 table
是类型 DataTable
在您的代码中,因此第一个索引器返回 DataRow
, ,第二个返回 object
. 。然后 PropertyInfo.SetValue
也有一个 object
作为第二个论点。在此代码中,任何位置都不会发生演员 在代码中, ,这就是为什么不应用超载转换操作员的原因。
一般来说,只有在已知静态类型时才应用(忘记 dynamic
目前在C#4.0中)。拳击和拆箱东西时不会应用。在这种情况下,索引器on DataRow
盒子值, PropertyInfo.SetValue
试图将其拆开到另一种类型 - 失败。
尽管我没有回答您的问题,但我认为在这种情况下,使用ORM框架(例如实体框架或NHIBERNATE)将您的表格映射到您的域对象并为您处理所有转换是更合适的。使用反射来找出填充域对象的字段是一种缓慢的方法。