Imports System.Reflection Namespace Dal Public Delegate Sub BeginLoadDelegate() Public Delegate Sub EndLoadDelegate(ByVal fields As Integer, ByVal objects As Integer) Public Delegate Function CommandHandler(Of T)(ByVal cmd As IDbCommand) As T Public Delegate Function ConnectionProviderDelegate() As IDbConnection Public Delegate Function TransactionProviderDelegate() As Data.IDbTransaction Public Class Loader ' Delegados para informar del comienzo y fin de la carga de los objetos Public Shared OnBeginLoad As BeginLoadDelegate = Nothing Public Shared OnEndLoad As EndLoadDelegate = Nothing Private Delegate Function FillObjectsDelegate(Of T)(ByVal dr As IDataReader, ByVal c As Dal.ConnectionProviderDelegate, ByVal t As Dal.TransactionProviderDelegate) As T Private Delegate Function FillObjectDelegate(Of T)(ByVal target As T, ByVal dr As IDataReader) As T Private Sub New() ' Constructor privado para evitar que se creen instancias de esta clase. End Sub #Region " Cargar un objeto " Public Shared Sub LoadObject(Of T As {Class, New, ILoader})(ByVal Target As T, ByVal dr As IDataReader, ByVal Loader_ As ObjectLoader) Try If OnBeginLoad IsNot Nothing Then OnBeginLoad() If dr.Read() Then PopulateObject(Target, dr, Loader_) If OnEndLoad IsNot Nothing Then OnEndLoad(Loader_.Campos.Count, 1) Catch Finally If dr.IsClosed = False Then dr.Close() End Try End Sub Public Shared Sub LoadObject(Of T As {Class, New, ILoader})(ByVal Target As T, ByVal dr As IDataReader) Try If OnBeginLoad IsNot Nothing Then OnBeginLoad() If dr.Read() Then PopulateObject(Target, dr) If OnEndLoad IsNot Nothing Then OnEndLoad(Target.GetObjectLoader.Campos.Count, 1) Catch Finally If dr.IsClosed = False Then dr.Close() End Try End Sub #End Region #Region " Creacion y carga de colecciones de objetos " Public Shared Function LoadObjects(Of T As {Class, New, ILoader})(ByVal Target As Generic.List(Of T), ByVal dr As IDataReader) As Generic.List(Of T) Return LoadObjects(Target, dr, New T().GetObjectLoader) End Function Public Shared s As Boolean = False Public Shared Function LoadObjects(Of T As {Class, New, ILoader})(ByVal Target As Generic.List(Of T), ByVal dr As IDataReader, ByVal Loader_ As ObjectLoader) As Generic.List(Of T) Try Dim iLoader As ILoader = DirectCast(Target, ILoader) '.GetObjectLoader ' Notificamos el inicio de la carga If OnBeginLoad IsNot Nothing Then OnBeginLoad() ' Se cachea el delegado creado dinamicamente If Loader_.FillObjectsDelegate Is Nothing Then Loader_.FillObjectsDelegate = MakeFillObjectsDelegate(Of T)(Loader_) Dim D As FillObjectsDelegate(Of T) = Loader_.FillObjectsDelegate Do Until dr.Read() = False Target.Add(D(dr, iLoader.ConnectionProvider, iLoader.transactionProvider)) Loop Catch Finally If dr.IsClosed = False Then dr.Close() End Try ' Notificamos el fin de la carga If OnEndLoad IsNot Nothing Then OnEndLoad(Loader_.Campos.Count, Target.Count) Return Target End Function #End Region Private Shared Function PopulateObject(Of T As {Class, New, ILoader})(ByVal Target As T, ByVal dr As IDataReader) As T Return PopulateObject(Target, dr, Target.GetObjectLoader) End Function Private Shared Function PopulateObject(Of T As {Class, New})(ByVal Target As T, ByVal dr As IDataReader, ByVal Cargador As ObjectLoader) As T Try If Cargador.FillObjectDelegate Is Nothing Then Cargador.FillObjectDelegate = MakeFillObjectDelegate(Of T)(Cargador) DirectCast(Cargador.FillObjectDelegate, FillObjectDelegate(Of T))(Target, dr) Catch ex As Exception Finally If dr.IsClosed = False Then dr.Close() End Try Return Target End Function Private Shared Function MakeFillObjectsDelegate(Of T)(ByVal loader As ObjectLoader) As FillObjectsDelegate(Of T) Dim Metodo As New Emit.DynamicMethod("", GetType(T), New Type() {GetType(IDataRecord), GetType(ConnectionProviderDelegate), GetType(TransactionProviderDelegate)}, GetType(T), True) With Metodo.GetILGenerator() ' Declarar Objeto de salida, Crearlo y Almacenarlo .DeclareLocal(GetType(T)) .Emit(Emit.OpCodes.Newobj, GetType(T).GetConstructor(Type.EmptyTypes)) .Emit(Emit.OpCodes.Stloc_0) For Each F As BindItem In loader.Campos Dim OmitirNullos As Emit.Label = .DefineLabel() ' Comprobar si el valor del campo es DbNull .Emit(Emit.OpCodes.Ldarg_0) ' DataRecord .Emit(Emit.OpCodes.Ldc_I4, F.fieldInfo.Index) ' Indice ' Llamada a la funcion .Emit(Emit.OpCodes.Callvirt, GetType(IDataRecord).GetMethod("IsDBNull")) ' Saltar a la etiqueta si hay null .Emit(Emit.OpCodes.Brtrue, OmitirNullos) ' Recuperar el valor del campo .Emit(Emit.OpCodes.Ldloc_0) ' Objeto Negocio .Emit(Emit.OpCodes.Ldarg_0) ' DataRecord .Emit(Emit.OpCodes.Ldc_I4, F.fieldInfo.Index) ' Indice .Emit(Emit.OpCodes.Callvirt, GetType(IDataRecord).GetMethod("get_Item", New Type() {GetType(Integer)})) Select Case True Case F.fieldInfo.DbType Is GetType(Integer) .Emit(Emit.OpCodes.Unbox_Any, GetType(Int32)) Case F.fieldInfo.DbType Is GetType(Double) .Emit(Emit.OpCodes.Unbox_Any, GetType(Double)) Case F.fieldInfo.DbType Is GetType(Decimal) .Emit(Emit.OpCodes.Unbox_Any, GetType(Decimal)) Case F.fieldInfo.DbType Is GetType(Boolean) .Emit(Emit.OpCodes.Unbox_Any, GetType(Boolean)) Case F.fieldInfo.DbType Is GetType(Date) .Emit(Emit.OpCodes.Callvirt, GetType(Object).GetMethod("ToString", Type.EmptyTypes)) End Select .Emit(Emit.OpCodes.Stfld, GetType(T).GetField("_" + F.PropertyName, BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.IgnoreCase)) '.Emit(Emit.OpCodes.Callvirt, GetType(T).GetProperty(F.PropertyName).GetSetMethod) .MarkLabel(OmitirNullos) Next .Emit(Emit.OpCodes.Ldloc_0) .Emit(Emit.OpCodes.Ldarg_1) .Emit(Emit.OpCodes.Callvirt, GetType(T).GetProperty("ConnectionProvider", BindingFlags.Public Or BindingFlags.Instance Or BindingFlags.IgnoreCase).GetSetMethod) '.Emit(Emit.OpCodes.Stfld, GetType(T).GetField("_ConnectionProvider", BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.IgnoreCase)) .Emit(Emit.OpCodes.Ldloc_0) .Emit(Emit.OpCodes.Ldarg_2) .Emit(Emit.OpCodes.Callvirt, GetType(T).GetProperty("TransactionProvider", BindingFlags.Public Or BindingFlags.Instance Or BindingFlags.IgnoreCase).GetSetMethod) '.Emit(Emit.OpCodes.Stfld, GetType(T).GetField("_TransactionProvider", BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.IgnoreCase)) ' Cargar el objeto y devolverlo .Emit(Emit.OpCodes.Ldloc_0) .Emit(Emit.OpCodes.Ret) End With Return Metodo.CreateDelegate(GetType(FillObjectsDelegate(Of T))) End Function Private Shared Function MakeFillObjectDelegate(Of T)(ByVal loader As ObjectLoader) As FillObjectDelegate(Of T) Dim Metodo As New Emit.DynamicMethod("", GetType(T), New Type() {GetType(T), GetType(IDataRecord)}, GetType(T), True) With Metodo.GetILGenerator() For Each F As BindItem In loader.Campos Dim OmitirNullos As Emit.Label = .DefineLabel() ' Comprobar si el valor del campo es DbNull .Emit(Emit.OpCodes.Ldarg_1) ' DataRecord .Emit(Emit.OpCodes.Ldc_I4, F.fieldInfo.Index) ' Indice ' Llamada a la funcion .Emit(Emit.OpCodes.Callvirt, GetType(IDataRecord).GetMethod("IsDBNull")) ' Saltar a la etiqueta si hay null .Emit(Emit.OpCodes.Brtrue, OmitirNullos) ' Recuperar el valor del campo .Emit(Emit.OpCodes.Ldarg_0) ' Objeto Negocio .Emit(Emit.OpCodes.Ldarg_1) ' DataRecord .Emit(Emit.OpCodes.Ldc_I4, F.fieldInfo.Index) ' Indice .Emit(Emit.OpCodes.Callvirt, GetType(IDataRecord).GetMethod("get_Item", New Type() {GetType(Integer)})) Select Case True Case F.fieldInfo.DbType Is GetType(Integer) .Emit(Emit.OpCodes.Unbox_Any, GetType(Int32)) Case F.fieldInfo.DbType Is GetType(Double) .Emit(Emit.OpCodes.Unbox_Any, GetType(Double)) Case F.fieldInfo.DbType Is GetType(Decimal) .Emit(Emit.OpCodes.Unbox_Any, GetType(Decimal)) Case F.fieldInfo.DbType Is GetType(Boolean) .Emit(Emit.OpCodes.Unbox_Any, GetType(Boolean)) Case F.fieldInfo.DbType Is GetType(Date) .Emit(Emit.OpCodes.Callvirt, GetType(Object).GetMethod("ToString", Type.EmptyTypes)) End Select .Emit(Emit.OpCodes.Stfld, GetType(T).GetField("_" + F.PropertyName, BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.IgnoreCase)) '.Emit(Emit.OpCodes.Callvirt, GetType(T).GetProperty(F.PropertyName).GetSetMethod) .MarkLabel(OmitirNullos) Next ' Cargar el objeto y devolverlo .Emit(Emit.OpCodes.Ldarg_0) .Emit(Emit.OpCodes.Ret) End With Return Metodo.CreateDelegate(GetType(FillObjectDelegate(Of T))) End Function End Class Public Interface ILoader Function GetObjectLoader() As ObjectLoader Property ConnectionProvider() As Dal.ConnectionProviderDelegate Property transactionProvider() As Dal.TransactionProviderDelegate End Interface Public Class ObjectLoader Public FillObjectDelegate As [Delegate] Public FillObjectsDelegate As [Delegate] Public C As Dal.ConnectionProviderDelegate = Nothing Public T As Dal.TransactionProviderDelegate = Nothing Private _Items As Generic.List(Of BindItem) Public Sub New() _Items = New Generic.List(Of BindItem) End Sub Public Sub Add(ByVal value As BindItem) _Items.Add(value) End Sub Default Public ReadOnly Property Item(ByVal Index As Integer) As BindItem Get Return _Items(Index) End Get End Property Public Function Campos() As Generic.List(Of BindItem) Return _Items End Function Public Function this() As ObjectLoader Return Me End Function End Class Public Class BindItem Public PropertyName As String Public fieldInfo As DbFieldInfo Public Sub New(ByVal propertyName As String, ByVal fieldName As String, ByVal fieldIndex As Integer, ByVal fieldDbType As Type) Me.PropertyName = propertyName With fieldInfo .Name = fieldName .Index = fieldIndex .DbType = fieldDbType End With End Sub End Class Public Structure DbFieldInfo Public Name As String Public Index As Integer Public DbType As Type End Structure End Namespace
martes, 16 de diciembre de 2008
Dal.Core.DataLoader.vb
Suscribirse a:
Enviar comentarios (Atom)
1 comentario:
Trace.WriteLine("0 : " + Parse(0))
Trace.WriteLine("1 : " + Parse(1))
Trace.WriteLine("2 : " + Parse(2))
Trace.WriteLine("3 : " + Parse(3))
Trace.WriteLine("4 : " + Parse(4))
Trace.WriteLine("5 : " + Parse(5))
Trace.WriteLine("16 : " + Parse(16))
Trace.WriteLine("34 : " + Parse(34))
Trace.WriteLine(String.Format("3 : {0}", Parse(New Integer() {1, 2})))
Trace.WriteLine(String.Format("1 : {0}", Parse(New Integer() {1})))
Trace.WriteLine(String.Format("0 : {0}", Parse(New Integer() {})))
Trace.WriteLine(String.Format("2 : {0}", Parse(New Integer() {2})))
Trace.WriteLine(String.Format("9 : {0}", Parse(New Integer() {1, 8})))
End Sub
Private Function Parse(ByVal value As Long) As String
Dim values As New Generic.List(Of String)
Dim potencia As Integer = 0
Do
Dim potenciaDeDos As Long = 2 ^ potencia
If (potenciaDeDos And value) = potenciaDeDos Then values.Add(potenciaDeDos)
potencia += 1
Loop While (2 ^ potencia) <= value
Return String.Join(",", values.ToArray)
End Function
Public Function parse(ByVal values As Integer()) As Long
Dim result As Long = 0
Dim x As Integer = 0
For x = 0 To values.Length - 1
result += values(x)
Next
Return result
End Function
Publicar un comentario