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「狂気」の例では、日付フィールドに、小数であると想定しているを入力しようとしているように見えます。それを見る必要があるかもしれません。

于 2012-05-08T19:08:29.693 に答える
0

そこで機能分解を再考する必要があると思います。1行を関数に移動してもあまり効果がありません.また、あなたがそうしようとしている方法で、型コンストラクターをジェネリックに渡すことはできないと思います. また、型チェックのいくつかを混乱させています。

代わりに、次の行に沿って何かを試してください。

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それ以外の場合は、チェックを実行して、例外をスローする値の型に代入しようとしないようにすることをお勧めします。または、構造を変更して、null 許容参照型を使用することもできます。つまり、次のようになります。

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

編集

LarsTech が指摘しているように、構造体のメンバーはプロパティではないため、構造体を変更してこれらのフィールドが実際にはプロパティであることを示すようにしない限り、これは期待どおりに機能しません。コンパイラーはゲッターとセッターを自動的に生成します。

于 2012-05-08T19:12:10.953 に答える