2017-05-09 36 views
0

我正在VB中開發一個ASP.NET MVC Web應用程序,我需要輸出一組數據到表格式,並允許用戶配置從可用集合中訂購和存在列。數據集存儲爲表示行模型的對象類型的列表。基於名稱作爲字符串訪問VB屬性 - 最快的選項

目前,我使用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() 

對於不同方法的建議可以使用。

+0

@VisualVincent是的,我認爲它會工作,但我對是否有性能優勢VS調用CallByName不清楚。 –

回答

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

0

如果ColumnName同名爲RowModel的屬性之一,我不明白爲什麼你需要的解決方法長與代表...

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) 
+0

你確定'CallByName'是瓶頸嗎?因爲與Reflection相比,它們似乎能夠以幾乎相同的速度獲得屬性(通常只需不到一毫秒即可完成)。 –

+0

我假設CallByName和System.Reflection方法的工作原理相同,所以我在考慮設置委託函數的哈希表來訪問屬性。我擔心這會在更新行模型時造成維護負擔。如果我可以動態地構建這組函數,那會更好。我想我的擔心是來自反射的性能影響來自哪裏。是當我迭代屬性集合,還是當我調用GetValue方法,或者兩者?我還沒有真正測試過我上面提出的任何方法。 –

+0

@ScottOliver:如果你使用你最後的代碼示例,那麼'HashSet'或'Dictionary'將會產生開銷。這是因爲你的最後一個代碼塊只是做了上面我做的更多的冗餘方式。 –

相關問題