これは、マップされたプロパティ属性に基づいてデータ行をオブジェクトにシリアル化する、私が取り組んできたシリアライザーです。[Delegate] .CreateDelegateを使用して速度を上げることに関連するいくつかの投稿を読んだので、それを試してみました。パフォーマンスはある程度向上したようですが、それは最小限です(すべてのオブジェクトタイプを最初にループして、すべての可能なプロパティ情報オブジェクトなどをキャッシュした後でも)。使用するすべての列名を完全に制御できるわけではないため、マップされたプロパティ情報には、割り当てることができる代替DB列名があります。また、マップしたいプロパティのみを取得します。
現在、約のシリアル化。オブジェクトごとに平均13個のプロパティを持つ1500個のオブジェクト、および1500個の親オブジェクト(子として)のそれぞれに含まれる平均3個のオブジェクトにも、1個あたり平均13個のプロパティが設定されています。
property.Name = row.Item( "columnName")
785ミリ秒を手動で設定する
p.SetValue1490
ミリ秒
GetSetMethod.Invoke1585
ミリ秒
[委任].CreateDelegate1285
ミリ秒
誰かがパフォーマンスを向上させるために私ができることをもっと提案できますか?
Friend Class DataSerializer(Of T As Class)
Private Shared MappedPropertiesCache As New Dictionary(Of Type, PropertyInfo())
Private Shared MappedColumnNameCache As New Dictionary(Of Type, List(Of String))
Private Shared ActionCache As New Dictionary(Of String, Action(Of T, Object))
Friend Shared Function SerializeDataRow(ByVal row As DataRow) As T
Dim target As Object = Activator.CreateInstance(GetType(T))
Dim targetType As Type = GetType(T)
AnalyzeMappedCache(target, targetType)
Dim index As Integer = 0
Dim mappedColumns As List(Of String) = MappedColumnNameCache.Item(targetType)
'iterate through target object properties
For Each p As PropertyInfo In MappedPropertiesCache.Item(targetType)
If row.Table.Columns.Contains(mappedColumns.Item(index)) Then
'' SLOW
'p.SetValue(target, CheckDbNull(row.Item(mappedColumns.Item(index))), Nothing)
'' SLOWER
'Dim methodInfo As MethodInfo = p.GetSetMethod()
'methodInfo.Invoke(target, New Object() {CheckDbNull(row.Item(mappedColumns.Item(index)))})
''FASTER THAN PREVIOUS TWO, BUT STILL SLOW
'Dim key As String = String.Format("{0}:{1}", target.GetType.FullName, p.Name)
'If Not ActionCache.ContainsKey(key) Then
' Dim methodAction As Action(Of T, Object) = MagicMethod(p.GetSetMethod())
' ActionCache.Add(key, methodAction)
'End If
'Dim param As Object = CheckDbNull(row.Item(mappedColumns.Item(index)))
'If Not param Is Nothing Then
' ActionCache(key)(target, param)
'End If
End If
index = index + 1
Next
Return target
End Function
Private Shared Function MagicMethod(method As MethodInfo) As Action(Of T, Object)
' First fetch the generic form
Dim genericHelper As MethodInfo = GetType(DataSerializer(Of T)).GetMethod("MagicMethodHelper", BindingFlags.[Static] Or BindingFlags.NonPublic)
' Now supply the type arguments
Dim constructedHelper As MethodInfo = genericHelper.MakeGenericMethod(GetType(T), method.GetParameters()(0).ParameterType)
' Now call it. The null argument is because it's a static method.
Dim ret As Object = constructedHelper.Invoke(Nothing, New Object() {method})
' Cast the result to the right kind of delegate and return it
Return DirectCast(ret, Action(Of T, Object))
End Function
Private Shared Function MagicMethodHelper(Of TTarget As Class, TParam)(method As MethodInfo) As Action(Of TTarget, Object)
' Convert the slow MethodInfo into a fast, strongly typed, open delegate
Dim func As Action(Of TTarget, TParam) = DirectCast([Delegate].CreateDelegate(GetType(Action(Of TTarget, TParam)), method), Action(Of TTarget, TParam))
' Now create a more weakly typed delegate which will call the strongly typed one
Dim ret As Action(Of TTarget, Object) = Sub(target As TTarget, param As Object) func(target, CType(param, TParam))
Return ret
End Function
Private Shared Sub AnalyzeMappedCache(ByVal target As Object, ByVal targetType As Type)
'this assumes the target object inherits from BaseProperties
If Not MappedPropertiesCache.ContainsKey(targetType) Then
Dim props As PropertyInfo() = target.GetMappedProperties()
Dim mappedColumnNameList As New List(Of String)
For Each prop As PropertyInfo In props
mappedColumnNameList.Add(CType(prop.GetCustomAttributes(GetType(DTO_POMGMT.MappedProperty), True).FirstOrDefault, DTO_POMGMT.MappedProperty).ColumnName)
Next
MappedColumnNameCache.Add(targetType, mappedColumnNameList)
MappedPropertiesCache.Add(targetType, props)
End If
End Sub
'check for a dbnull value of any object type returned from database
Private Shared Function CheckDbNull(ByVal obj As Object) As Object
Return If(obj Is DBNull.Value, Nothing, obj)
End Function
End Class