我目前正在处理一个应用程序,在该应用程序中我需要从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)将您的表格映射到您的域对象并为您处理所有转换是更合适的。使用反射来找出填充域对象的字段是一种缓慢的方法。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top