[VB.NET/C#]Declaratief type meegeven aan templated function

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • DarthDavy
  • Registratie: Januari 2007
  • Laatst online: 06-06 16:12

DarthDavy

Excellent!

Topicstarter
Gebruikt framework is .NET 3.5.

Volgende generieke Read functio om tabellen uit te lezen en de data op te slaan in business objecten waarvan de properties dezelfde naam hebben als de kolommen in de tabellen.

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    Private Function Read(Of T)(ByVal sql As String) As List(Of T)
        Dim list As List(Of T) = New List(Of T)()
        Dim propertyInfoList As List(Of PropertyInfo) = GetType(T).GetProperties().ToList()
        Using reader As OracleDataReader = OdpHelper.ExecuteReader(CommandType.Text, sql)
            Dim nextResult As Boolean = True
            Do Until Not nextResult
                Do While reader.Read()
                    Dim obj As T = Activator.CreateInstance(Of T)()
                    For i As Integer = 0 To reader.FieldCount - 1 Step 1
                        Dim propertyName As String = reader.GetName(i)
                        Dim pi As PropertyInfo = propertyInfoList.Where(Function(f) f.Name.ToUpper() = propertyName).Single()
                        If pi.PropertyType Is GetType(String) Then
                            pi.SetValue(obj, Me.GetObjectOrDefault(Of String)(reader, propertyName), Nothing)
                        ElseIf pi.PropertyType Is GetType(Integer) Then
                            pi.SetValue(obj, Me.GetObjectOrDefault(Of Integer)(reader, propertyName), Nothing)
                        ElseIf pi.PropertyType Is GetType(DateTime) Then
                            pi.SetValue(obj, Me.GetObjectOrDefault(Of DateTime)(reader, propertyName), Nothing)
                        End If
                    Next
                    list.Add(obj)
                Loop
                nextResult = reader.NextResult()
            Loop
            reader.Close()
        End Using
        Return list
    End Function

    Private Function GetObjectOrDefault(Of T)(ByVal reader As OracleDataReader, ByVal key As String) As T
        Dim ordinal As Integer = reader.GetOrdinal(key)
        If reader.IsDBNull(ordinal) Then
            Return Nothing
        Else
            Return DirectCast(reader.Item(ordinal), T)
        End If
    End Function


Het is volgende stuk code dat een doorn in mijn oog is
Visual Basic .NET:
1
2
3
4
5
6
7
If pi.PropertyType Is GetType(String) Then
  pi.SetValue(obj, Me.GetObjectOrDefault(Of String)(reader, propertyName), Nothing)
ElseIf pi.PropertyType Is GetType(Integer) Then
  pi.SetValue(obj, Me.GetObjectOrDefault(Of Integer)(reader, propertyName), Nothing)
ElseIf pi.PropertyType Is GetType(DateTime) Then
  pi.SetValue(obj, Me.GetObjectOrDefault(Of DateTime)(reader, propertyName), Nothing)
End If


Ik zou dus in de code moeten gaan scannen welke alle mogelijke types zijn, terwijl ik dat type al weet door pi.PropertyType, maar ik kan GetObjectOrDefault niet oproepen als
Visual Basic .NET:
1
pi.SetValue(obj, Me.GetObjectOrDefault(Of pi.PropertyType)(reader, propertyName), Nothing)

De compiler vindt dat niet zo leuk en terecht, maar ik weet niet hoe ik dit anders zou kunnen doen.

Weet er iemand raad, want het is ook niet zo eenvoudig om hierop te googlen en een antwoord te vinden?

Antwoord mag gerust ook in C# (het is niet mijn keuze dat het momenteel in VB.NET is :P ).

Bier zonder alcohol is zoals een BH aan de wasdraad: het beste is eruit


Acties:
  • 0 Henk 'm!

  • Daspeed
  • Registratie: Maart 2001
  • Laatst online: 17:53
Kun je ipv directcast niet beter iets gebruiken als Convert.Changetype?

Acties:
  • 0 Henk 'm!

  • DarthDavy
  • Registratie: Januari 2007
  • Laatst online: 06-06 16:12

DarthDavy

Excellent!

Topicstarter
Inderdaad

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Private Function Read(Of T)(ByVal sql As String) As List(Of T)
        Dim list As List(Of T) = New List(Of T)()
        Dim propertyInfoList As List(Of PropertyInfo) = GetType(T).GetProperties().ToList()
        Using reader As OracleDataReader = OdpHelper.ExecuteReader(CommandType.Text, sql)
            Dim nextResult As Boolean = True
            Do Until Not nextResult
                Do While reader.Read()
                    Dim obj As T = Activator.CreateInstance(Of T)()
                    For i As Integer = 0 To reader.FieldCount - 1 Step 1
                        Dim propertyName As String = reader.GetName(i)
                        Dim pi As PropertyInfo = propertyInfoList.Where(Function(f) f.Name.ToUpper() = propertyName).Single()
                        pi.SetValue(obj, Me.GetObjectOrDefault(reader, propertyName, pi.PropertyType), Nothing)
                    Next
                    list.Add(obj)
                Loop
                nextResult = reader.NextResult()
            Loop
            reader.Close()
        End Using
        Return list
    End Function

    Private Function GetObjectOrDefault(ByVal reader As OracleDataReader, ByVal key As String, ByVal tType As Type) As Object
        Dim ordinal As Integer = reader.GetOrdinal(key)
        If reader.IsDBNull(ordinal) Then
            Return Nothing
        Else
            Return Convert.ChangeType(reader.Item(ordinal), tType)
        End If
    End Function


Stuk properder. Thx!

Bier zonder alcohol is zoals een BH aan de wasdraad: het beste is eruit


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:03
Verander die GetObjectOrDefault method , zodanig dat deze niet meer generic is, maar gewoon een Type als parameter meekrijgt.
De return waarde kan van het type object zijn, want die SetValue method accepteert toch een parameter van het type object.

/eh, ja, zoals je dus ondertussen gedaan hebt dus :P

[ Voor 10% gewijzigd door whoami op 13-08-2010 08:48 ]

https://fgheysels.github.io/