Etiketler

, , , ,


Reflection ile Dinamik Entity Eşleme (Mapping) | Referans Tipleri Dinamik Olarak Clone’lama

Birçok projenizde verilerinizi öncelikle geçici bir tabloya kaydedip, daha sonra bu verileri ana tablonuza aktarmanız gerekebilir. Örneğin, bir veri giriş operatörüne verdiğiniz tüm formu girmesini isteyip, daha sonra bu verileri alıp, düzenleyip ana tablonuza kaydetmek isteyebilirsiniz. Bunu yapmanın sayısız yolu vardır. Ben bu yazımda veri tabanı tarafında bulacağınız çözümlerden, Sql ( SELECT FOR INSERT ) bahsetmeyeceğim. Entity üzerine kurgulanmış bir sisteminiz varsa ve tablolara tüm erişiminizi (Select, insert, update, delete … için) entityler üzerinden gerçekleştiriyorsanız, geçici ve ana tablo üzerindeki tüm alanları tek tek birbirine eşleme (mapping) ihtiyacınızı, dinamik olarak çözme yönteminden bahsedeceğim.

İhtiyacımız, iki farklı entity deki aynı isimde olan özellikler (property) arasında değer aktarımı gerçekleştirmektir. (İsimlerle bağımlık yaratmaktansa, Attribute kullanılmasını tavsiye ederim.) Geçici tablodaki alanların değerlerini, ana tabloya aktarmak için, geçici tabloya ait entity sınıfının property lerindeki değerleri, ana tablodaki property lere atamamız gerekmektedir.

Dinamik olarak bunu çözmenin yolu ister istemez yansıma (reflection) yönteminden geçmektedir. Bunun için öncelikle geçici tablodaki property’lerin bilgilerini

sourceEntity.GetType().GetProperties()

metoduyla alır ve bu dizideki tüm propertyler için

propertyInfo.GetValue(sourceEntity, Nothing)

ile sırayla tüm property lerin değerlerini alır ve

propertyInfoOfTarget.SetValue(targetEntity, setValueToTargetProperty, BindingFlags.SetProperty, Nothing, Nothing, Nothing)

ana tablodaki property e kaydederiz.

”’
    ”’ Özellikle CreateLike ile oluşturulmuş tablolarda,
    ”’ temp tablodan gerçek tabloya veri atmamız gerektiğinde,
    ”’ farklı entity lerdeki değerleri dinamik olarakbirbirlerine atamak için
    ”’ hazırlanmış bir sınıftır.
    ”’
    Public Class EntityMapper
        ”’
        ”’ Özellikle CreateLike ile oluşturulmuş tablolarda,
        ”’ temp tablodan gerçek tabloya veri atmamız gerektiğinde,
        ”’ farklı entity lerdeki değerleri dinamik olarakbirbirlerine atamak için
        ”’ hazırlanmış bir metotdur.
        ”’ Aynı isimde olan property değerlerini birbirleriyle eşler.
        ”’
        ”’ Kaynakdaki verileri hedefdeki alanlara aktarır.
        ”’ Kaynakdaki veriler korunur. (değişmez)
        ”’ Hedefdeki verileri, kaynakdaki verileri ile değiştirilir.Kaynak, hedefde eşleşen [property] alanlarını ezer. (kendi değeri yazar)
        ”’
        ”’ Değerleriokunacak entity
        ”’ Değerlerinyazılacağı entity
        ”’
        Public Function FromSourceToTargetEntity(Of S, T As {New, BaseEntity})(ByValsourceEntity As S,ByRef targetEntity AsT) As T
            ‘ Kaynak ve Hedef nesnelerin tüm [property] bilgieleriokunur.
            Dim propertiesOfSource AsPropertyInfo() =sourceEntity.GetType().GetProperties()
            Dim propertiesOfTarget AsPropertyInfo() =targetEntity.GetType().GetProperties()
            ‘Kaynağın her bir [property] si üzerinde dolaşılarak
            For Each propertyInfoAs PropertyInfoIn propertiesOfSource
               Dim propertyName As String = propertyInfo.Name
                If(propertyInfo.CanRead) Then
                   ‘Aktarılacak değer alınır (GetValue ile )
                   Dim getValueOfSourceProperty As Object =propertyInfo.GetValue(sourceEntity, Nothing)
                   Dim setValueToTargetProperty As Object =getValueOfSourceProperty
                   ‘Hedefte aktarılacak [property] bulunur.
                   Dim propertyInfoOfTarget As PropertyInfo = Nothing
                   For index AsInteger = 0 TopropertiesOfTarget.Count – 1
                        If(propertiesOfTarget(index).Name = propertyName) Then
                           propertyInfoOfTarget = propertiesOfTarget(index)
                            Exit For
                        End If
                   Next
                   ‘Kaynaktan alınan değer, hedefin ilgili[property] sine atanır. (SetValue ile)
                   If (Not Object.ReferenceEquals(propertyInfoOfTarget, Nothing)) Then
                        If (propertyInfo.CanWrite) Then
                           propertyInfoOfTarget.SetValue(targetEntity, setValueToTargetProperty, BindingFlags.SetProperty, Nothing,Nothing, Nothing)
                        End If
                   End If
               End If
            Next
            Return targetEntity
        End Function
        ”’
        ”’
        ”’
        ”’ Web servis entegrasyon işlemleri için tasarlanmıştır.
        ”’ discardChar karakteri haric okunacak ve yazılacakentity’nin property isimleri aynı (büyük küçük harf duyarlılığı yok) olanproperty’leri
        ”’ eşler.
        ”’
        ”’
        ”’ Değerleriokunacak entity
        ”’ Değerlerinyazılacağı entity
        ”’ Goz ardıedilecek karakter. (bu karakter haric okunacak ve yazılacak entity’nin propertyisimleri aynı (büyük küçük harf duyarlılığı yok)
        ”’
        Public Function FromSourceToTargetEntity(Of S, T As {New})(ByVal sourceEntity AsS, ByReftargetEntity As T,ByRef discardChar AsString) As T
            ‘ Kaynak ve Hedef nesnelerin tüm [property] bilgieleriokunur.
            DimpropertiesOfSource As PropertyInfo()= sourceEntity.GetType().GetProperties()
            Dim propertiesOfTarget AsPropertyInfo() =targetEntity.GetType().GetProperties()
            ‘Kaynağın her bir [property] si üzerinde dolaşılarak
            For Each propertyInfo As PropertyInfo InpropertiesOfSource
               Dim propertyName As String =propertyInfo.Name.Replace(discardChar, String.Empty).ToUpper()
               If (propertyInfo.CanRead) Then
                   ‘Aktarılacak değer alınır (GetValue ile )
                   Dim getValueOfSourceProperty As Object =propertyInfo.GetValue(sourceEntity, Nothing)
                   Dim setValueToTargetProperty As Object =getValueOfSourceProperty
                   ‘Hedefte aktarılacak [property] bulunur.
                   Dim propertyInfoOfTarget As PropertyInfo = Nothing
                   For index AsInteger = 0 TopropertiesOfTarget.Count – 1
                        If (propertiesOfTarget(index).Name.ToUpper(System.Globalization.CultureInfo.GetCultureInfo(“en-US”)) = propertyName) Then
                           propertyInfoOfTarget = propertiesOfTarget(index)
                            Exit For
                        End If
                   Next
                   ‘Kaynaktan alınan değer, hedefin ilgili[property] sine atanır. (SetValue ile)
                   If (Not Object.ReferenceEquals(propertyInfoOfTarget, Nothing)) Then
                        If (propertyInfo.CanWrite) Then
                           propertyInfoOfTarget.SetValue(targetEntity, setValueToTargetProperty, BindingFlags.SetProperty, Nothing,Nothing, Nothing)
                        End If
                   End If
               End If
            Next
            ReturntargetEntity
        End Function
        Public FunctionFromDataTableToEntityCollection(Of S As DataTable, T As {New, BaseEntity})(ByRefsourceDataTable As S)As IEnumerable(Of T)
            Dim entityCollection AsNew List(Of T)
            Dim targetEntity As T
            Dim propertiesOfTarget AsPropertyInfo() = GetType(T).GetProperties()
            Dim columnsOfDataTable AsDataColumnCollection =sourceDataTable.Columns
            For Each row As DataRow In sourceDataTable.Rows
               targetEntity = New T()
               For EachcolumnInfo As DataColumnIn columnsOfDataTable
                   Dim columnName AsString = columnInfo.ColumnName
                   Dim getValueOfTheColumnAtTheRow As Object =row.Item(columnName)
                   ‘Hedefte aktarılacak [property] bulunur.
                   Dim propertyInfoOfTarget As PropertyInfo = Nothing
                   For index AsInteger = 0 TopropertiesOfTarget.Count – 1
                        If (propertiesOfTarget(index).Name = columnName) Then
                           propertyInfoOfTarget = propertiesOfTarget(index)
                            If (NotIsDBNull(getValueOfTheColumnAtTheRow)) Then
                               Dim setValueToTargetProperty AsObject =CTypeDynamic(getValueOfTheColumnAtTheRow, propertyInfoOfTarget.PropertyType)
                                ‘Kaynaktan alınan değer, hedefin ilgili [property] sineatanır. (SetValue ile)
                               If (Not Object.ReferenceEquals(propertyInfoOfTarget, Nothing)) Then
                                    If (propertiesOfTarget(index).CanWrite) Then
                                       propertyInfoOfTarget.SetValue(targetEntity, setValueToTargetProperty, BindingFlags.SetProperty, Nothing,Nothing, Nothing)
                                    End If
                                End If
                            End If
                            Exit For
                        End If
                   Next
               Next
               entityCollection.Add(targetEntity)
            Next
            Return entityCollection
        End Function
    End Class

Bu sayede aynı zamanda referans tipler arasında değer(value) aktarımı da yapmak için, yani farklı ref adresine sahip iki aynı değerlere sahip instance elde etmede de kullanabilirsiniz.  Yukarıdaki fonksiyonlar ile dinamik olarak referans tipleri clone’layabilirsiniz.

Görüşmek üzere,