【问题标题】:Access VB property based on name as string - Fastest Option基于名称作为字符串访问 VB 属性 - 最快的选项
【发布时间】:2017-05-09 11:15:26
【问题描述】:

我正在用 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()

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

【问题讨论】:

  • @VisualVincent 是的,我认为它会起作用,但我不清楚与调用 CallByName 相比是否有性能优势。

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


【解决方案1】:

我做了类似的事情来将 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 方面的需求

【讨论】:

    【解决方案2】:

    如果ColumnNameRowModel 的属性之一同名,我不明白您为什么需要长时间的代理解决方法...

    extension method 现在只获取您想要的属性,速度更快,内存消耗更少。

    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)
    

    【讨论】:

    • 您确定CallByName 是瓶颈吗?因为与反射相比,它们似乎都能够以几乎同样快的速度获得属性(通常需要不到一毫秒的时间)。
    • 我假设 CallByName 和 System.Reflection 方法在后台工作相同,因此我考虑设置委托函数的哈希表来访问属性。我担心的是,这会在更新行模型时造成维护负担。如果我可以动态构建那组函数,那就更好了。我想我担心的是反射对性能的影响来自哪里。是在我迭代属性集合时,还是在我调用 GetValue 方法时,还是两者兼而有之?我还没有实际测试过我上面提出的任何方法。
    • @ScottOliver :如果您使用最后一个代码示例,那么 HashSetDictionary 将产生开销。这是因为你的最后一个代码块只是我上面做的一种更冗余的方式。
    • @ScottOliver :我相信反射总是会有一定的开销(尽管每次调用仍然只有大约 1 毫秒),因为它必须执行大量调用和评估。 因此最快的方法是在第一个代码块中执行此操作,因为它不使用反射。因此,通过获得性能,您会失去“动态性”。
    • @ScottOliver :检查以下问题中的答案,它可能会有所帮助:stackoverflow.com/questions/1027980/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 1970-01-01
    • 2016-07-30
    • 2020-01-14
    • 2016-01-16
    • 1970-01-01
    相关资源
    最近更新 更多