[WebServices] Copiare i valori da una business entity "originale" a quella proxy creata da VS e viceversa.

Se utilizziamo nella nostra soluzione delle custom entities che posizioniamo in un assembly a se stante possiamo ovviamente referenziare lo stesso sia dal progetto che contiene il web service, sia dal progetto client che lo consuma.

Possiamo veicolare queste entità (oggetti) attraverso il web service (rimando a riguardo all'ottimo webcast di Andrea), ma sul client noi non utilizziamo la classe vera e propria che abbiamo definito, ma solo una sorta di mezzo-clone che assomiglia a quella classe.

Quando ho dovuto affrontare il problema sono stato costretto (vista l'urgenza) a cavarmi d'impaccio copiando barbaramente, proprietà per proprietà, tutti i valori. In seguito, parlandone al volo dopo un evento, Andrea mi suggeriva di utilizzare Reflection per risolvere il problema.

Purtroppo anche riguardandomi i suoi 3 webcast sui web services non ho trovato qualche riferimento a questo problema (bisogna dire che le Q&A però sono state tagliate...) ed allora, visto che Reflection era uno di quegli argomenti che non avevo mai avuto modo di affrontare "realmente", ho deciso di scrivermi una funzioncina che cerca semplicemente di copiare i valori delle proprietà e dei campi che trova all'interno della classe. Probabilmente non era proprio quello che intendeva #Andrea quando mi ha detto "devi usare Reflection", e ovviamente immagino che esistano funzioni e/o strumenti molto più completi ed efficaci, ma come "studio" di sicuro mi è servito! Se a qualcun'altro interessa... sono curioso (come sempre) di conoscere le vostre opinioni!

Attenzione: la funzione non è stata testata ed è stata "buttata lì" a scopo didattico! Non credo sia il caso di usarla senza prima verificarne realmente la corretta funzionalità!

 

    Public Shared Function WSEntityCopyTo(ByVal sourceObject As Object, ByVal targetType As Type) As Object
        'Scritta da Mario Duzioni
        'http://blogs.ugidotnet.org/duz
        'http://www.duzioni.com
        'Commenti e critiche costruttive sono sempre bene accette
        'Rev.0 - 08/06/2005

        Dim sourceType As Type = sourceObject.GetType
        Dim result As Object = Activator.CreateInstance(targetType)

        'Cerco tutti i membri pubblici
        Dim destMembers As Reflection.MemberInfo()
        Dim newValue As Object
        Dim sourceMemberType As Type
        Dim targetMemberType As Type
        Dim complexMemberType As Boolean

        'Recupera tutti i membri
        For Each sourceMember As Reflection.MemberInfo In sourceType.GetMembers()

            'Cerca solo campi e proprietà
            If sourceMember.MemberType = Reflection.MemberTypes.Field Or sourceMember.MemberType = Reflection.MemberTypes.Property Then
                'Cerco se esiste lo stesso membro nella destinazione
                destMembers = targetType.GetMember(sourceMember.Name)

                'Se trova il membro prova a copiare il valore
                Select Case destMembers.Length
                    Case Is = 1

                        'Ottiene i tipi di sorgente e destinazione
                        Select Case sourceMember.MemberType
                            Case Reflection.MemberTypes.Field
                                sourceMemberType = DirectCast(sourceMember, Reflection.FieldInfo).FieldType
                            Case Reflection.MemberTypes.Property
                                sourceMemberType = DirectCast(sourceMember, Reflection.PropertyInfo).PropertyType
                        End Select
                        Select Case destMembers(0).MemberType
                            Case Reflection.MemberTypes.Field
                                targetMemberType = DirectCast(destMembers(0), Reflection.FieldInfo).FieldType
                            Case Reflection.MemberTypes.Property
                                targetMemberType = DirectCast(destMembers(0), Reflection.PropertyInfo).PropertyType
                        End Select

                        'Verifica che si tratti di un campo o di una proprietà
                        If sourceMember.MemberType = Reflection.MemberTypes.Field Or sourceMember.MemberType = Reflection.MemberTypes.Property Then

                            'Leggo il valore a seconda che sia un campo o una proprietà
                            Select Case sourceMember.MemberType
                                Case Reflection.MemberTypes.Field
                                    newValue = DirectCast(sourceMember, Reflection.FieldInfo).GetValue(sourceObject)
                                Case Reflection.MemberTypes.Property
                                    'Presume che la proprietà non sia indicizzata
                                    newValue = DirectCast(sourceMember, Reflection.PropertyInfo).GetValue(sourceObject, Nothing)
                            End Select

                            'Controlla se il tipo del membro è uguale
                                If Not sourceMemberType Is targetMemberType Then

                                'SOpporta anche il Null...
                                If Not newValue Is Nothing Then
                                    'Se non è uguale o è un altro UDT oppure è incompatibile
                                    Try
                                        newValue = ConvertTo(newValue, targetMemberType)
                                    Catch ex As Exception
                                        'Sollevo un eccezione: i due tipi non sono compatibili!
                                        Throw New ArgumentException("The source object type does not match the return type!")
                                    End Try
                                End If

                            End If '/Controlla se il tipo del membro è uguale

                            'Setto il valore a seconda che sia un campo o una proprietà
                            Select Case destMembers(0).MemberType
                                Case Reflection.MemberTypes.Field
                                    DirectCast(destMembers(0), Reflection.FieldInfo).SetValue(result, newValue)
                                Case Reflection.MemberTypes.Property
                                    'Presume che la proprietà non sia indicizzata
                                    DirectCast(destMembers(0), Reflection.PropertyInfo).SetValue(result, newValue, Nothing)
                            End Select

                        End If '/Verifica che si tratti di un campo o di una proprietà

                    Case Is > 1
                        'Sollevo un eccezione: la copia potrebbe risultare ambigua!
                        Throw New Exception(String.Format("There are more members named ""{0}"" in the return type", sourceMember.Name))
                End Select

            End If

        Next '/Recupera tutti i membri pubblici

        Return result

    End Function

Print | posted @ mercoledì 8 giugno 2005 19:47

Comments on this entry:

Gravatar # [WebServices] Copiare i valori da una business entity
by TheDuzBlog! ;-p at 08/06/2005 19:52

Gravatar # re: [WebServices] Copiare i valori da una business entity "originale" a quella proxy creata da VS e viceversa.
by ralp at 11/05/2007 13:35

si potrebbe avere in C#
Gravatar # re: [WebServices] Copiare i valori da una business entity "originale" a quella proxy creata da VS e viceversa.
by Mario Duzioni at 11/05/2007 13:48

Al momento purtroppo ce l'ho solo in VB :-(

Se ti può aiutare comunque esistono dei convertitori automatici come questo: http://www.developerfusion.co.uk/utilities/convertvbtocsharp.aspx

Non sono infallibili, comunque tutto sommato riescono a convertire la maggior parte del codice.

Il mio consiglio è di convertirlo in automatico e poi di controllarlo passo-passo, in modo da capire anche "cosa fa" esattamente.

NOTA BENE: E' codice non testato in tutti gli scenari, pubblicato più che altro come spunto. Non utilizzarlo in produzione senza aver prima verificato a dovere il comportamento!
Comments have been closed on this topic.