babsevensix

Il blog di Alberto
posts - 94, comments - 81, trackbacks - 11

Parsing del file di Mapping

Ecco il mio primo post, nel mio primo blog...

Oggi volevo trattare con voi Parsing dei file di Mapping creati per NHibernate.

Innanzitutto, a cosa può servire? Nel mio caso ad esempio per effettuare delle ricerche utilizzando le expression di NHibernate in modo tale da poter generalizzare un form che, passando una entity specifica, mi indichi tutte le proprietà ad essa associate.

Iniziamo dunque dalla prima classe, presa direttamente dalla seguente pagina web :

http://weblogs.domain-driven.net/default,date,2006-09-25.aspx

Quindi convertiamo la classe in VB.NET e successivamente l’estendiamo.

 

TypeMappingParser.vb

 

Imports System

Imports System.Collections

Imports System.Reflection

Imports System.Reflection.Emit

 

Imports NHibernate

Imports NHibernate.Metadata

Imports NHibernate.Type

Imports NHibernate.Bytecode

Imports NHibernate.Mapping

Imports NHibernate.Loader

 

Public Enum AssociationType

    OneToOne

    OneToMany

    ManyToOne

    Component

End Enum

 

Public Class TypeMappingParser

 

    Private _typeMappings As Hashtable

 

    Public Sub New(ByVal factory As ISessionFactory)

        ParseMappings(factory)

    End Sub

 

    Public Function GetTypeMappingInfo(ByVal typeName As String) As TypeMappingInfo

        Return CType(_typeMappings(typeName), TypeMappingInfo)

    End Function

 

    Private Sub ParseMappings(ByVal factory As ISessionFactory)

        _typeMappings = New Hashtable()

        IdentifyMappedTypes(factory)

        ParseMappedTypes(factory)

    End Sub

 

    Private Sub IdentifyMappedTypes(ByVal factory As ISessionFactory)

 

        For Each type As Type In factory.GetAllClassMetadata().Keys

 

            'Dim icmd As IClassMetadata = factory.GetClassMetadata(type)

            Dim typeMappingInfo As TypeMappingInfo = New TypeMappingInfo(type)

            _typeMappings.Add(type.Name, typeMappingInfo)

        Next

    End Sub

 

    Private Sub ParseMappedTypes(ByVal factory As ISessionFactory)

 

        For Each type As Type In factory.GetAllClassMetadata().Keys

            ParsePropertiesAndAssociations(factory, type)

        Next

 

    End Sub

 

    Private Sub ParsePropertiesAndAssociations(ByVal factory As ISessionFactory, ByVal type As Type)

 

        Dim propertyIndex As Integer = 0

 

        Dim classMeta As IClassMetadata = CType(factory.GetAllClassMetadata()(type), IClassMetadata)

        Dim containingTypeMappingInfo As TypeMappingInfo = GetTypeMappingInfo(type.Name)

 

        For Each propertyType As IType In classMeta.PropertyTypes

 

            If (propertyType.IsAssociationType) Then

 

                ParseEntity(factory, containingTypeMappingInfo, propertyType, classMeta.PropertyNames(propertyIndex))

 

            ElseIf (propertyType.IsComponentType) Then

 

                ParseComponentType(factory, containingTypeMappingInfo, propertyType, classMeta.PropertyNames(propertyIndex))

 

            Else

                ParseValue(containingTypeMappingInfo, propertyType, classMeta.PropertyNames(propertyIndex))

            End If

            propertyIndex += 1

        Next

    End Sub

 

    Private Sub ParseComponentType(ByVal factory As ISessionFactory, ByVal containingTypeInfo As TypeMappingInfo, ByVal propertyType As IType, ByVal propertyName As String)

 

        If (Not _typeMappings.Contains(propertyType.Name)) Then

 

            Dim desc As TypeMappingInfo = New TypeMappingInfo(propertyType.ReturnedClass)

            _typeMappings.Add(propertyType.Name, desc)

 

            Dim entityPropInfo As New EntityPropertyInfo( _

                    containingTypeInfo, _

                    propertyType.ReturnedClass, _

                    propertyName, _

                    GetAssociationType(propertyType, False))

 

            'entityPropInfo.TypeMappingInfo = desc

 

            containingTypeInfo.AddProperty(entityPropInfo)

 

            Dim compType As IAbstractComponentType = CType(propertyType, IAbstractComponentType)

 

            For index As Integer = 0 To compType.PropertyNames.Length - 1

 

                Dim subType As IType = compType.Subtypes(index)

                If (subType.IsAssociationType) Then

 

                    ParseEntity(factory, desc, subType, compType.PropertyNames(index))

 

                ElseIf (subType.IsComponentType) Then

 

                    ParseComponentType(factory, desc, subType, compType.PropertyNames(index))

 

                Else

 

                    ParseValue(desc, subType, compType.PropertyNames(index))

                End If

            Next

 

        Else

 

            containingTypeInfo.AddProperty( _

                New EntityPropertyInfo(containingTypeInfo, _

                 propertyType.ReturnedClass, _

                 propertyName, _

                 GetAssociationType(propertyType, False)))

        End If

    End Sub

 

    Private Sub ParseValue(ByVal containingTypeMappingInfo As TypeMappingInfo, ByVal propertyType As IType, ByVal propertyName As String)

 

        Dim info As ValuePropertyInfo = New ValuePropertyInfo(containingTypeMappingInfo, _

             propertyType.ReturnedClass, _

             propertyName)

 

        containingTypeMappingInfo.AddProperty(info)

    End Sub

 

    Private Sub ParseEntity(ByVal factory As ISessionFactory, ByVal containingTypeInfo As TypeMappingInfo, _

            ByVal propertyType As IType, ByVal propertyName As String)

 

        If (propertyType.IsEntityType) Then

 

            Dim info As EntityPropertyInfo = _

                New EntityPropertyInfo(containingTypeInfo, _

                 propertyType.ReturnedClass, _

                 propertyName, _

                 GetAssociationType(propertyType, False))

 

            containingTypeInfo.AddProperty(info)

 

        Else

            Dim collectionMeta As ICollectionMetadata = _

                            factory.GetCollectionMetadata((CType(propertyType, CollectionType)).Role)

 

 

 

            If (TypeOf collectionMeta.ElementType Is ComponentType) Then

 

                Dim componentType As ComponentType = CType(collectionMeta.ElementType, ComponentType)

 

                Dim info As EntityPropertyInfo = _

                    New EntityPropertyInfo(containingTypeInfo, _

                     componentType.ReturnedClass, _

                     propertyName, _

                     GetAssociationType(componentType, True))

 

                containingTypeInfo.AddProperty(info)

 

            ElseIf (TypeOf collectionMeta.ElementType Is ManyToOneType) Then

 

                Dim info As EntityPropertyInfo = New EntityPropertyInfo( _

                    containingTypeInfo, _

                    collectionMeta.ElementType.ReturnedClass, _

                    propertyName, _

                    GetAssociationType(collectionMeta.ElementType, True))

                containingTypeInfo.AddProperty(info)

            Else

                Throw New ApplicationException("Collection type " & collectionMeta.ElementType.Name & " was not recognized")

            End If

        End If

    End Sub

 

    Private Function GetAssociationType(ByVal type As IType, ByVal isCollection As Boolean) As AssociationType

 

        If (TypeOf type Is ManyToOneType AndAlso isCollection) Then

            Return AssociationType.OneToMany

 

        ElseIf (TypeOf type Is ManyToOneType) Then

            Return AssociationType.ManyToOne

        ElseIf (TypeOf type Is OneToOneType) Then

            Return AssociationType.OneToOne

        Else

            Return AssociationType.OneToOne

        End If

    End Function

 

End Class

 

Si può notare che, nel costruttore della classe si passi l'ISessionFactory; tramite questa semplice interfaccia, disponibile in NHibernate, si riesce a sapere qualunque cosa di qualunque entity mappata correttamente nel nostro assembly.

Inizierà dunque il parsing veri e proprio costruendosi una struttura identificando da prima le varie entity e quindi le varie proprietà di ognuna di esse stabilendo le eventuali relazioni tra i vari oggetti.

Sucessivamente per avere le informazioni dell'entity A, ad esempio, basta richiamare il metodo GetTypeMappingInfo("A") il quale restituirà un oggetto di tipo TypeMappingInfo

 

TypeMappingInfo.vb

 

Public Class TypeMappingInfo

 

 

    Private _type As Type

    Private _listProperty As IList(Of IPropertyInfo)

 

    Sub New(ByVal type As Type)

        Me._type = type

 

        Me._listProperty = New List(Of IPropertyInfo)

    End Sub

 

    Public Sub AddProperty(ByVal obj As IPropertyInfo)

        Me._listProperty.Add(obj)

    End Sub

 

    Public ReadOnly Property ListProperty() As IList(Of IPropertyInfo)

        Get

            Return Me._listProperty

        End Get

    End Property

 

    Public ReadOnly Property TypeClass() As System.Type

        Get

            Return Me._type

        End Get

    End Property

 

    Public Overrides Function ToString() As String

        Return Me._type.Name

    End Function

End Class

 

Questa classe è il contenitore delle informazioni dell'entity richiesta. Oltretutto tramite la property TypeClass posso creare nuovi oggetti del tipo indicato.

Nel prossimo post vedo di allegare anche il resto del codice, con una semplice spiegazione del funzionamento dello stesso e del suo possibile utilizzo.

Un saluto a tutti

Alberto B.B.

 

Print | posted on venerdì 9 marzo 2007 20:05 |

Feedback

Gravatar

# Parsing del file di Mapping

10/03/2007 11:41 | blogs.ugidotnet.org
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET