1

我继承了一些糟糕的 vb.net 代码,并且在尝试找出用于循环当前结构的泛型时遇到了麻烦。

这是结构的片段

    Public Structure ApplicationDetails
    Dim ID As Integer
    Dim AgentID As Integer
    Dim ApplicationDate As Date
    Dim CompletedDate As Date

这是填充它的疯狂

With ApplicationInfo
            .ID = If(Not IsDBNull(DT(0)("ID")), DT(0)("ID"), Nothing)
            .ApplicationDate = If(Not IsDBNull(DT(0)("ApplicationDate")), DT(0)("MortgageAmount"), Nothing)
            .CompletedDate = If(Not IsDBNull(DT(0)("CompleteDate")), DT(0)("MortgageAmount"), Nothing)

现在我想做这样的事情:

       For Each item In ApplicationInfo.GetType().GetProperties()
            Dim thisType = item.GetType()
            Dim name = item.Name
            Dim value = DtItem(Of item.GetType())(0, name.ToString(), DT)
            item.SetValue(item, value, Nothing)
        Next
Private Function DtItem(Of T)(ByVal num As Integer, ByVal name As String, ByRef DT As DataTable) As T
    Return If(Not IsDBNull(DT(num)(name)), DT(num)(name), Nothing)
End Function

但我不确定设置值的语法,并且在尝试获取类型时我得到 item.GetTYpe() 未声明。我知道我必须走在正确的轨道上,只是错过了一些东西。

4

2 回答 2

2

若干问题。

首先,SetValue仅适用于对象类型,而不适用于值,因此您必须将结构更改为类。

Public Class ApplicationDetails
End Class

接下来,您正在遍历属性,但您的“结构”只有字段。所以你需要添加属性:

Public Class ApplicationDetails
  Private _ID As Integer

  Property ID As Integer
    Get
      Return _ID
    End Get
    Set(ByVal value As Integer)
      _ID = value
    End Set
  End Property

  //' etc

End Class

否则,您将不得不使用GetFields.

我认为泛型在这里不起作用,因为您只处理对象并且您不知道类型(尽管有反射):

Private Function DtItem(ByVal num As Integer, ByVal name As String, ByRef DT As DataTable) As Object
  Return If(Not IsDBNull(DT(num)(name)), DT(num)(name), Nothing)
End Function

最后,您的反射调用是错误的。尝试将其更改为:

For Each item As PropertyInfo In ApplicationInfo.GetType().GetProperties
  Dim value As Object = DtItem(0, item.Name, _dt)
  If item.CanWrite Then
    item.SetValue(ApplicationInfo, value, Nothing)
  End If
Next

我不确定通过反思来做这件事是否会给你带来任何好处。在您的“疯狂”示例中,看起来您可能正在尝试将MortgageAmount我假设为小数的 a 放入日期字段中。这可能需要看看。

于 2012-05-08T19:08:29.693 回答
0

我认为您需要重新考虑那里的功能分解。将一行移到函数中并没有太多好处,而且我认为您无法像尝试这样做的方式将类型构造函数传递给泛型。您还混淆了一些类型检查。

请尝试以下方法:

For Each item In ApplicationInfo.GetType().GetProperties()
    Dim theName As String = item.Name,
        isNullable = Not item.PropertyType.IsValueType OrElse _
                     Nullable.GetUnderlyingType(item.PropertyType) IsNot Nothing

    If item.CanWrite Then
        If Not IsDBNull(DT(0)(theName))
            item.SetValue(ApplicationInfo, DT(0)(theName), Nothing)
        ElseIf isNullable
            item.SetValue(ApplicationInfo, Nothing, Nothing)
        End If
    End If
Next

如果您的代码在对象初始化后立即执行,则isNullable检查是无关的,您可以简单地不采取任何措施,因为属性将被初始化为 null。否则,我建议您执行检查,这样您就不会尝试分配Nothing给会引发异常的值类型。或者,您可以修改结构以使用可为空的引用类型,即:

Public Structure ApplicationDetails
    Property ID As Integer?
    Property AgentID As Integer?
    Property ApplicationDate As Date?
    Property CompletedDate As Date?
End Structure

编辑

正如 LarsTech 指出的那样,您的结构成员不是属性,除非您修改结构以指示这些字段实际上是属性,否则编译器将自动为其生成 getter 和 setter 。

于 2012-05-08T19:12:10.953 回答