基于名称作为字符串访问VB属性 - 最快的选项

时间:2017-05-09 11:15:26

标签: asp.net vb.net reflection system.reflection

我正在用VB开发一个ASP.NET MVC Web应用程序,我需要输出一组数据到表格格式,并允许用户配置可用集合中列的顺序和存在。数据集存储为表示行模型的对象类型列表。

目前,我使用CallByName实现此目的。迭代有序的属性名列表并从行模型的实例输出值。但是,基于测试,这似乎是该过程中的一个主要瓶颈。

我已经看到了一个建议来存储代理来获取属性,而不是该属性名称的字符串表示形式。所以,我可能会做这样的事情:

Public Delegate Function GetColumn(ByRef RowObj As RowModel) As String

Dim GetPropOne As GetColumn = Function(ByRef RowObj As RowModel) RowObj.Prop1.ToString()

Dim accessors As New Hashtable()

accessors.Add("Prop1", GetPropOne)

然后,循环并执行以下操作:

Dim acc As GetColumn = accessors(ColumnName)

Dim val As String = acc.Invoke(currentRow)

它看起来更快,但它看起来更像是维护。如果这确实更快,有没有办法可以动态构建这样的东西?我在想:

Public Delegate Function GetObjectProperty(Instance As Object) As Object

For Each prop In GetType(RowModel).GetProperties()
    Dim acc As GetObjectProperty = AddressOf prop.GetValue
    columns.Add(prop.Name, acc)
Next

Dim getColVal As GetObjectProperty = columns(ColumnName)

Dim val As String = getColVal.Invoke(currentRow).ToString()

对不同方法的建议持开放态度。

2 个答案:

答案 0 :(得分:0)

我做类似的事情将SOAP响应变成数据表

Public Function ObjectToDataSource(objName) As DataSet
    Dim CollName = ""
    Dim ds As New DataSet()
    For Each m As System.Reflection.PropertyInfo In objName.GetType().GetProperties()
        If m.CanRead Then
            If InStr(m.PropertyType.ToString, "[]") <> 0 Then
                CollName = m.Name
                Exit For
            End If
        End If
    Next
    Dim CollObj
    CollObj = CallByName(objName, CollName, CallType.Get)
    If CollObj.length = 0 Then
        Call EndTask("No Supply Chains to display", "Royal Mail failed to return Supply Chain information for these credentials", 3)
    Else
        Dim dt_NewTable As New DataTable(CollName)
        ds.Tables.Add(dt_NewTable)
        Dim ColumnCount = 0
        For Each p As System.Reflection.PropertyInfo In CollObj(0).GetType().GetProperties()
            If p.CanRead Then
                If p.Name <> "ExtensionData" Then
                    dt_NewTable.Columns.Add(p.Name, p.PropertyType)
                    ColumnCount = ColumnCount + 1
                End If
            End If
        Next
        Dim rowcount = CollObj.Length - 1
        For r = 0 To rowcount
            Dim rowdata(ColumnCount - 1) As Object
            For c = 0 To ColumnCount - 1
                rowdata(c) = CallByName(CollObj(r), dt_NewTable.Columns.Item(c).ToString, CallType.Get)
            Next
            dt_NewTable.Rows.Add(rowdata)
            rowdata = Nothing
        Next
    End If
    Return ds
End Function

这特定于我在获取CollName和不需要ExtensionData

方面的需求

答案 1 :(得分:0)

如果ColumnNameRowModel的某个属性名称相同,我不明白为什么您需要代理的长解决方法......

this event emitter只获得您想要的属性,速度更快,占用内存更少。

Imports System.Runtime.CompilerServices

Public Module Extensions

    <Extension()> _
    Public Function GetProperty(ByVal Instance As Object, ByVal PropertyName As String, Optional ByVal Arguments As Object() = Nothing) As Object
        Return Instance.GetType().GetProperty(PropertyName).GetValue(Instance, Arguments)
    End Function
End Module

使用示例:

currentRow.GetProperty("Prop1")
'or:
currentRow.GetProperty(ColumnName)