151 lines
5.9 KiB
VB.net
151 lines
5.9 KiB
VB.net
Imports System.Runtime.CompilerServices
|
|
Imports System.Reflection
|
|
Imports System.Data
|
|
|
|
Namespace Extensiones
|
|
Public Module IEnumerableExtensions
|
|
|
|
<Extension()>
|
|
Public Function CopyToDataTable(Of T)(ByVal source As IEnumerable(Of T)) As DataTable
|
|
Return New ObjectShredder(Of T)().Shred(source, Nothing, Nothing)
|
|
End Function
|
|
|
|
<Extension()>
|
|
Public Function CopyToDataTable(Of T)(ByVal source As IEnumerable(Of T), ByVal table As DataTable, ByVal options As LoadOption?) As DataTable
|
|
Return New ObjectShredder(Of T)().Shred(source, table, options)
|
|
End Function
|
|
|
|
End Module
|
|
End Namespace
|
|
|
|
Public Class ObjectShredder(Of T)
|
|
Private _fi As FieldInfo()
|
|
Private _pi As PropertyInfo()
|
|
Private _ordinalMap As Dictionary(Of String, Integer)
|
|
Private _type As Type
|
|
|
|
Public Sub New()
|
|
_type = GetType(T)
|
|
_fi = _type.GetFields()
|
|
_pi = _type.GetProperties.Where(Function(x) Not (x.PropertyType.Name.Contains("EntityReference") OrElse x.PropertyType.Name.Contains("EntityCollection") OrElse x.PropertyType.Name.Contains("EntityState") OrElse x.PropertyType.Name.Contains("EntityKey") OrElse x.PropertyType.BaseType.Name = "EntityObject")).ToArray
|
|
_ordinalMap = New Dictionary(Of String, Integer)()
|
|
End Sub
|
|
|
|
Public Function Shred(ByVal source As IEnumerable(Of T), ByVal table As DataTable, ByVal options As LoadOption?) As DataTable
|
|
If GetType(T).IsPrimitive Then
|
|
Return ShredPrimitive(source, table, options)
|
|
End If
|
|
|
|
If table Is Nothing Then
|
|
table = New DataTable(GetType(T).Name)
|
|
End If
|
|
|
|
table = ExtendTable(table, GetType(T))
|
|
table.BeginLoadData()
|
|
|
|
Using e As IEnumerator(Of T) = source.GetEnumerator()
|
|
|
|
While e.MoveNext()
|
|
|
|
If options IsNot Nothing Then
|
|
table.LoadDataRow(ShredObject(table, e.Current), CType(options, LoadOption))
|
|
Else
|
|
table.LoadDataRow(ShredObject(table, e.Current), True)
|
|
End If
|
|
End While
|
|
End Using
|
|
|
|
table.EndLoadData()
|
|
Return table
|
|
End Function
|
|
|
|
Public Function ShredPrimitive(ByVal source As IEnumerable(Of T), ByVal table As DataTable, ByVal options As LoadOption?) As DataTable
|
|
If table Is Nothing Then
|
|
table = New DataTable(GetType(T).Name)
|
|
End If
|
|
|
|
If Not table.Columns.Contains("Value") Then
|
|
table.Columns.Add("Value", GetType(T))
|
|
End If
|
|
|
|
table.BeginLoadData()
|
|
|
|
Using e As IEnumerator(Of T) = source.GetEnumerator()
|
|
Dim values As Object() = New Object(table.Columns.Count - 1) {}
|
|
|
|
While e.MoveNext()
|
|
values(table.Columns("Value").Ordinal) = e.Current
|
|
|
|
If options IsNot Nothing Then
|
|
table.LoadDataRow(values, CType(options, LoadOption))
|
|
Else
|
|
table.LoadDataRow(values, True)
|
|
End If
|
|
End While
|
|
End Using
|
|
|
|
table.EndLoadData()
|
|
Return table
|
|
End Function
|
|
|
|
Public Function ExtendTable(ByVal table As DataTable, ByVal type As Type) As DataTable
|
|
For Each f As FieldInfo In type.GetFields()
|
|
|
|
If Not _ordinalMap.ContainsKey(f.Name) Then
|
|
Dim dc As DataColumn = If(table.Columns.Contains(f.Name), table.Columns(f.Name), table.Columns.Add(f.Name, f.FieldType))
|
|
_ordinalMap.Add(f.Name, dc.Ordinal)
|
|
End If
|
|
Next
|
|
Dim Propiedades = type.GetProperties.Where(Function(x) Not (x.PropertyType.Name.Contains("EntityReference") OrElse x.PropertyType.Name.Contains("EntityCollection") OrElse x.PropertyType.Name.Contains("EntityState") OrElse x.PropertyType.Name.Contains("EntityKey") OrElse x.PropertyType.BaseType.Name = "EntityObject"))
|
|
|
|
For Each p As PropertyInfo In Propiedades
|
|
|
|
If Not _ordinalMap.ContainsKey(p.Name) Then
|
|
Dim propiedad = p.PropertyType
|
|
If propiedad Is GetType(Integer?) Then
|
|
propiedad = GetType(Integer)
|
|
ElseIf propiedad Is GetType(Double?) Then
|
|
propiedad = GetType(Double)
|
|
ElseIf propiedad Is GetType(Long?) Then
|
|
propiedad = GetType(Long)
|
|
ElseIf propiedad Is GetType(Boolean?) Then
|
|
propiedad = GetType(Boolean)
|
|
ElseIf propiedad Is GetType(DateTime?) Then
|
|
propiedad = GetType(DateTime)
|
|
ElseIf propiedad Is GetType(Date?) Then
|
|
propiedad = GetType(Date)
|
|
End If
|
|
Dim dc As DataColumn = If(table.Columns.Contains(p.Name), table.Columns(p.Name), table.Columns.Add(p.Name, propiedad))
|
|
_ordinalMap.Add(p.Name, dc.Ordinal)
|
|
End If
|
|
Next
|
|
|
|
Return table
|
|
End Function
|
|
|
|
Public Function ShredObject(ByVal table As DataTable, ByVal instance As T) As Object()
|
|
Dim fi As FieldInfo() = _fi
|
|
Dim pi As PropertyInfo() = _pi
|
|
|
|
If instance.[GetType]() <> GetType(T) Then
|
|
ExtendTable(table, instance.[GetType]())
|
|
fi = instance.[GetType]().GetFields()
|
|
pi = instance.[GetType]().GetProperties.Where(Function(x) Not (x.PropertyType.Name.Contains("EntityReference") OrElse x.PropertyType.Name.Contains("EntityCollection") OrElse x.PropertyType.Name.Contains("EntityState") OrElse x.PropertyType.Name.Contains("EntityKey") OrElse x.PropertyType.BaseType.Name = "EntityObject")).ToArray
|
|
End If
|
|
|
|
Dim values As Object() = New Object(table.Columns.Count - 1) {}
|
|
|
|
For Each f As FieldInfo In fi
|
|
values(_ordinalMap(f.Name)) = f.GetValue(instance)
|
|
Next
|
|
|
|
For Each p As PropertyInfo In pi
|
|
values(_ordinalMap(p.Name)) = p.GetValue(instance, Nothing)
|
|
Next
|
|
|
|
Return values
|
|
End Function
|
|
End Class
|
|
|
|
|