Skip to content

Commit

Permalink
- refactoring - more methods marked as overridable
Browse files Browse the repository at this point in the history
- enum types featured
- begin transaction methods refactored
- register connection bugfix
- try/catch added into statements toXxxxx() methods
- supporting assigning rows to Object
  • Loading branch information
tomFlidr committed Nov 12, 2017
1 parent 765a40e commit 703950a
Show file tree
Hide file tree
Showing 26 changed files with 1,646 additions and 1,442 deletions.
60 changes: 30 additions & 30 deletions ActiveRecord/Entity/DatabaseGetters/Init.vb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Imports System.ComponentModel
Imports System.ComponentModel
Imports System.Dynamic
Imports System.Reflection

Expand All @@ -17,34 +17,34 @@ Namespace ActiveRecord
Me.initResource()
End Sub

''' <summary>
''' Initializes 'Resource' class member (static or instance) with singleton Resource instance,
''' if there is no instance yet. This method is always called by Entity constructor.
''' </summary>
Protected Sub initResource()
Dim meType As Type = Me.GetType()
Dim resourceMember As Reflection.MemberInfo = (
From
member As Reflection.MemberInfo In meType.GetMembers(
BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic
)
Where
member.Name = "Resource" AndAlso (
TypeOf member Is Reflection.PropertyInfo OrElse
TypeOf member Is Reflection.FieldInfo
)
Select
member
).FirstOrDefault()
If resourceMember = Nothing Then Return
If TypeOf resourceMember Is Reflection.PropertyInfo Then
Dim pi As Reflection.PropertyInfo = DirectCast(resourceMember, Reflection.PropertyInfo)
If pi.GetValue(Me, Nothing) = Nothing AndAlso pi.CanWrite Then pi.SetValue(Me, Resource.GetInstance(pi.PropertyType), Nothing)
ElseIf TypeOf resourceMember Is Reflection.FieldInfo Then
Dim fi As Reflection.FieldInfo = DirectCast(resourceMember, Reflection.FieldInfo)
If fi.GetValue(Me) = Nothing Then fi.SetValue(Me, Resource.GetInstance(fi.FieldType))
End If
End Sub
''' <summary>
''' Initializes 'Resource' class member (static or instance) with singleton Resource instance,
''' if there is no instance yet. This method is always called by Entity constructor.
''' </summary>
Protected Overridable Sub initResource()
Dim meType As Type = Me.GetType()
Dim resourceMember As Reflection.MemberInfo = (
From
member As Reflection.MemberInfo In meType.GetMembers(
BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic
)
Where
member.Name = "Resource" AndAlso (
TypeOf member Is Reflection.PropertyInfo OrElse
TypeOf member Is Reflection.FieldInfo
)
Select
member
).FirstOrDefault()
If resourceMember = Nothing Then Return
If TypeOf resourceMember Is Reflection.PropertyInfo Then
Dim pi As Reflection.PropertyInfo = DirectCast(resourceMember, Reflection.PropertyInfo)
If pi.GetValue(Me, Nothing) = Nothing AndAlso pi.CanWrite Then pi.SetValue(Me, Resource.GetInstance(pi.PropertyType), Nothing)
ElseIf TypeOf resourceMember Is Reflection.FieldInfo Then
Dim fi As Reflection.FieldInfo = DirectCast(resourceMember, Reflection.FieldInfo)
If fi.GetValue(Me) = Nothing Then fi.SetValue(Me, Resource.GetInstance(fi.FieldType))
End If
End Sub

End Class
End Class
End Namespace
206 changes: 121 additions & 85 deletions ActiveRecord/Entity/DatabaseReader/Privates.vb
Original file line number Diff line number Diff line change
@@ -1,91 +1,127 @@
Imports System.Data.Common
Imports System.Data.Common
Imports Databasic.ActiveRecord

Namespace ActiveRecord
Partial Public MustInherit Class Entity
Partial Public MustInherit Class Entity

''' <summary>
''' Get column names from reader as list of strings.
''' </summary>
''' <param name="reader"></param>
''' <returns></returns>
Private Shared Function _getReaderRowColumns(reader As DbDataReader) As List(Of String)
Return Enumerable.ToList(Of String)(
Enumerable.Select(Of Integer, String)(
Enumerable.Range(0, reader.FieldCount),
New Func(Of Integer, String)(AddressOf reader.GetName)
)
)
End Function
''' <summary>
''' Return True if type is descriptable type by custom attributes, not primitive, not an object.
''' </summary>
''' <param name="instanceType">Instance type to check out.</param>
''' <returns>True if descriptable.</returns>
Private Shared Function _isDescriptableType(ByRef instanceType As Type) As Boolean
Return Not instanceType.IsPrimitive AndAlso instanceType.FullName <> "System.String" AndAlso instanceType.FullName <> "System.Object"
End Function
''' <summary>
''' Set up current reader row columns into instance properties and fields.
''' </summary>
''' <param name="reader">DbDataReader with current row moved, where current row will be used to fill instance properties and fields.</param>
''' <param name="readerColumnNames">Columns in reader in proper order.</param>
''' <param name="instance">Instance to fill.</param>
Private Shared Sub _readerRowToInstance(ByRef reader As DbDataReader, ByRef readerColumnNames As List(Of String), ByRef columnsByDbNames As Dictionary(Of String, Databasic.MemberInfo), ByRef instance As Object, isEntity As Boolean)
Dim mi As Databasic.MemberInfo
Dim rawValueTypeCode As TypeCode
Dim assigned As Boolean
Dim propInfo As Reflection.PropertyInfo
Dim targetName As String
Dim formatProvider As IFormatProvider
Dim rawValue As Object
Dim targetValue As Object
Dim entity As Databasic.ActiveRecord.Entity
For Each readerColumnName As String In readerColumnNames
assigned = False
rawValue = reader(readerColumnName)
targetName = readerColumnName
targetValue = Nothing
If columnsByDbNames.ContainsKey(readerColumnName) Then
mi = columnsByDbNames(readerColumnName)
rawValueTypeCode = Type.GetTypeCode(rawValue.GetType())
If (rawValueTypeCode = Constants.StringTypeCode AndAlso mi.TrimChars.Length > 0) Then
rawValue = rawValue.ToString().Trim(mi.TrimChars)
ElseIf rawValueTypeCode = Type.GetTypeCode(mi.Type) Then
targetValue = rawValue
ElseIf mi.Type.IsEnum Then
targetValue = System.[Enum].Parse(mi.Type, rawValue.ToString())
Else
formatProvider = If(mi.FormatProvider, System.Globalization.CultureInfo.CurrentCulture)
targetValue = If(TypeOf rawValue Is DBNull, Nothing, Convert.ChangeType(rawValue, mi.Type, formatProvider))
End If
If (mi.MemberInfoType = MemberInfoType.Prop) Then
propInfo = DirectCast(mi.MemberInfo, Reflection.PropertyInfo)
If propInfo.CanWrite Then
propInfo.SetValue(instance, targetValue, Nothing)
assigned = True
Else
targetName = mi.Name
End If
Else
DirectCast(mi.MemberInfo, Reflection.FieldInfo).SetValue(instance, targetValue)
assigned = True
End If
End If
If isEntity Then
targetValue = If(targetValue, rawValue)
entity = DirectCast(instance, Databasic.ActiveRecord.Entity)
If Not assigned Then
entity._reserveStore.Item(targetName) = targetValue
End If
If entity._initialData.ContainsKey(targetName) Then
entity._initialData(targetName) = targetValue
Else
entity._initialData.Add(targetName, targetValue)
End If
End If
Next
End Sub
''' <summary>
''' Get column names from reader as list of strings.
''' </summary>
''' <param name="reader"></param>
''' <returns></returns>
Private Shared Function _getReaderRowColumns(reader As DbDataReader) As List(Of String)
Return Enumerable.ToList(Of String)(
Enumerable.Select(Of Integer, String)(
Enumerable.Range(0, reader.FieldCount),
New Func(Of Integer, String)(AddressOf reader.GetName)
)
)
End Function
''' <summary>
''' Set up current reader row columns into instance properties and fields.
''' </summary>
''' <param name="reader">DbDataReader with current row moved, where current row will be used to fill instance properties and fields.</param>
''' <param name="readerColumnNames">Columns in reader in proper order.</param>
''' <param name="instance">Instance to fill.</param>
Private Shared Sub _readerRowToTypedInstance(
ByRef reader As DbDataReader,
ByRef readerColumnNames As List(Of String),
ByRef columnsByDbNames As Dictionary(Of String, Databasic.MemberInfo),
ByRef instance As Object,
isEntity As Boolean
)
Dim mi As Databasic.MemberInfo
Dim rawValueTypeCode As TypeCode
Dim assigned As Boolean
Dim propInfo As Reflection.PropertyInfo
Dim targetName As String
Dim formatProvider As IFormatProvider
Dim rawValue As Object
Dim targetValue As Object
For Each readerColumnName As String In readerColumnNames
assigned = False
rawValue = reader(readerColumnName)
targetName = readerColumnName
targetValue = Nothing
If columnsByDbNames.ContainsKey(readerColumnName) Then
mi = columnsByDbNames(readerColumnName)
rawValueTypeCode = Type.GetTypeCode(rawValue.GetType())
If (rawValueTypeCode = Constants.StringTypeCode AndAlso mi.TrimChars.Length > 0) Then
rawValue = rawValue.ToString().Trim(mi.TrimChars)
ElseIf rawValueTypeCode = Type.GetTypeCode(mi.Type) Then
targetValue = rawValue
ElseIf mi.Type.IsEnum Then
targetValue = Entity._parseEnumMemberValue(mi, rawValue)
Else
formatProvider = If(mi.FormatProvider, System.Globalization.CultureInfo.CurrentCulture)
targetValue = If(TypeOf rawValue Is DBNull, Nothing, Convert.ChangeType(rawValue, mi.Type, formatProvider))
End If
If (mi.MemberInfoType = MemberInfoType.Prop) Then
propInfo = DirectCast(mi.MemberInfo, Reflection.PropertyInfo)
If propInfo.CanWrite Then
propInfo.SetValue(instance, targetValue, Nothing)
assigned = True
End If
Else
DirectCast(mi.MemberInfo, Reflection.FieldInfo).SetValue(instance, targetValue)
assigned = True
End If
targetName = mi.Name
End If
If isEntity Then
Entity._setUpentityValueToReserveStoreAndInitialValues(
DirectCast(instance, Databasic.ActiveRecord.Entity),
targetName, rawValue, targetValue, assigned
)
End If
Next
End Sub

End Class
Private Shared Sub _readerRowToAnonymousInstance(
ByRef reader As DbDataReader,
ByRef readerColumnNames As List(Of String),
ByRef instance As Databasic.Object
)
For Each readerColumnName As String In readerColumnNames
Entity._setUpentityValueToReserveStoreAndInitialValues(
instance, readerColumnName, Nothing, reader(readerColumnName), False
)
Next
End Sub

Private Shared Function _parseEnumMemberValue(mi As MemberInfo, rawValue As Object) As Object
If mi.UseEnumUnderlyingValue Then
Dim underType As Type = System.Enum.GetUnderlyingType(mi.Type),
underValue = Convert.ChangeType(rawValue, underType),
values = System.[Enum].GetValues(mi.Type)
For i = 0 To values.Length - 1
If (underValue = values(i)) Then
Return values(i)
End If
Next
Return Nothing
Else
Return System.[Enum].Parse(mi.Type, rawValue.ToString())
End If
End Function

Private Shared Sub _setUpentityValueToReserveStoreAndInitialValues(
entity As Databasic.ActiveRecord.Entity,
targetName As String,
rawValue As Object,
targetValue As Object,
assigned As Boolean
)
targetValue = If(targetValue, rawValue)
If Not assigned Then
entity._reserveStore.Item(targetName) = targetValue
End If
If entity._initialData.ContainsKey(targetName) Then
entity._initialData(targetName) = targetValue
Else
entity._initialData.Add(targetName, targetValue)
End If
End Sub

End Class
End Namespace
Loading

0 comments on commit 703950a

Please sign in to comment.