mardi 24 novembre 2015

Reflection Optimization

I've recently implemented reflection to replace the more tedious aspects of our data retrieval from a SQL database. The old code would look something like this:

_dr = _cmd.ExecuteReader (_dr is the SQLDataReader)
        While _dr.Read (_row is a class object with public properties)
                _row.Property1 = Convert.ToInt16(_dr("Prop1"))
                _row.Property2 = Convert.ToInt16(_dr("Prop2"))
                _row.Property3 = Convert.ToInt16(_dr("Prop3"))
                If IsDBNull(_dr("Prop4")) = False Then _row.Prop4 = _dr("Prop4")
...

Since my code base has a lot of functionality like this, reflection seemed like a good bet to simplify it and make future coding easier. How to assign datareader data into generic List ( of T ) has a great answer that was practically like magic for my needs and easily translated into VB. For easy reference:

Public Shared Function GenericGet(Of T As {Class, New})(ByVal reader As SqlDataReader, ByVal typeString As String)
    'Dim results As New List(Of T)()
    Dim results As Object

    If typeString = "List" Then
        results = New List(Of T)()
    End If

    Dim type As Type = GetType(T)

    Try
        If reader.Read() Then
            ' at least one row: resolve the properties
            Dim props As PropertyInfo() = New PropertyInfo(reader.FieldCount - 1) {}
            For i As Integer = 0 To props.Length - 1
                Dim prop = type.GetProperty(reader.GetName(i), BindingFlags.Instance Or BindingFlags.[Public])
                If prop IsNot Nothing AndAlso prop.CanWrite Then
                    props(i) = prop
                End If
            Next

            Do
                Dim obj = New T()
                For i As Integer = 0 To props.Length - 1
                    Dim prop = props(i)
                    If prop Is Nothing Then
                        Continue For
                    End If
                    ' not mapped
                    Dim val As Object = If(reader.IsDBNull(i), Nothing, reader(i))
                    If val IsNot Nothing Then SetValue(obj, prop, val)
                Next

                If typeString = "List" Then
                    results.Add(obj)
                Else
                    results = obj
                End If

            Loop While reader.Read()
        End If

    Catch ex As Exception
        Helpers.LogMessage("Error: " + ex.Message + ". Stacktrace: " + ex.StackTrace)
    End Try
    Return results
End Function

The only caveat with this is that it is somewhat slower.

My question is how to optimize. Sample code I find online is all in C# and does not convert neatly into VB. Scenario 4 here seems like exactly what I want, but converting it to VB gives all kinds of errors (Using CodeFusion or converter.Telerik.com).

Has anyone done this in VB before? Or can anyone translate what's in that last link?

Any help's appreciated.





Aucun commentaire:

Enregistrer un commentaire