Passa ai contenuti principali

VB for Dummies: La serializzazione – parte 1

Questo post è dedicato alla serializzazione e a come sia possibile sfruttarla in Visual Basic.

Partiamo con una definizione di serializzazione presa da Wikipedia:

In informatica, la serializzazione è un processo per salvare un oggetto in un supporto di memorizzazione lineare (ad esempio, un file o un'area di memoria), o per trasmetterlo su una connessione di rete. La serializzazione può essere in forma binaria o può utilizzare codifiche testuali (ad esempio il formato XML) direttamente leggibili dagli esseri umani. Lo scopo della serializzazione è di trasmettere l'intero stato dell'oggetto in modo che esso possa essere successivamente ricreato nello stesso identico stato dal processo inverso, chiamato deserializzazione.

In sostanza si tratta di poter “scrivere” l’oggetto in un formato standard per poter essere “ricostruito” in un momento successivo, in un’altra applicazione o, addirittura in altri linguaggi e piattaforme di sviluppo.

In questo post tralasceremo la serializzazione binaria e ci occuperemo delle tre principali modalità di serializzazione testuali utilizzate: XML, SOAP e JSON.

Poichè serializzare significa prendere un nostro oggetto e “trasformarlo” in una stringa (in parole veramente molto semplici) con un determinato formato, dobbiamo partire da un oggetto e per fare questo creiamo una classe fattura (molto semplice!!) che utilizzeremo nei nostri esperimenti:

image

Le classi in gioco sono, evidentemente molto semplici e servono esclusivamente da esempio senza avere la pretesa di essere esaustive.

La proprietà Totale della classe Fattura è di tipo ReadOnly (così come Totale e Totale Ivato del Dettaglio Fattura) e vedremo come questo influenza la serializzazione.

In dettagli le classi sono le seguenti:

  1. Imports System.Xml.Serialization
  2.  
  3. Public Class Fattura
  4.     Public Sub New()
  5.         Dettagli = New List(Of DettaglioFattura)
  6.     End Sub
  7.  
  8.     Public Property DataEmissione As DateTime
  9.     Public Property Cliente As Cliente
  10.     Public Property NumeroDocumento As String
  11.     Public Property Dettagli As List(Of DettaglioFattura)
  12.     Public Property Stato As StatoFattura
  13.  
  14.     Public ReadOnly Property Totale As Decimal
  15.         Get
  16.             If Dettagli Is Nothing Then
  17.                 Return 0
  18.             Else
  19.                 Return Dettagli.Sum(Function(d) d.TotaleIvato)
  20.             End If
  21.         End Get
  22.     End Property
  23.  
  24. End Class

 

  1. Public Class DettaglioFattura
  2.  
  3.     Public Property Descrizione As String
  4.     Public Property Codice As String
  5.     Public Property Quantita As Integer
  6.     Public Property PrezzoUnitario As Decimal
  7.     Public Property Iva As Decimal
  8.  
  9.     Public ReadOnly Property Totale As Decimal
  10.         Get
  11.             Return Quantita * PrezzoUnitario
  12.         End Get
  13.     End Property
  14.  
  15.     Public ReadOnly Property TotaleIvato As Decimal
  16.         Get
  17.             Return Totale * (1 + Iva)
  18.         End Get
  19.     End Property
  20. End Class

 

  1. Public Class Cliente
  2.  
  3.     Public Property Denominazione As String
  4.     Public Property CodiceFiscale As String
  5.     Public Property PartitaIVA As String
  6.  
  7. End Class

 

  1. Public Enum StatoFattura
  2.     DaPagare
  3.     Pagata
  4.     Annullata
  5. End Enum

 

Serializzazione in XML

Il primo tipo di serializzazione che vedremo è quello XML, cioè vedremo come “scrivere” le istanze della nostra classe fattura in formato XML.

Per poter serializzare una nostra classe in formato XML, la classe stessa deve essere serializzabile, ovvero composta da proprietà (i metodi non vengono serializzati) serializzabili. Se, ad esempio la nostra classe contiene una proprietà di un tipo .NET non serializzabile l’intera classe non è serializzabile.

Il processo di serializzazione si basa sull’utilizzo della classe XmlSerializer e di un oggetto che serva da flusso in cui scrivere l’XML risultante (un XmlWriter, un TextWriter, uno Stream).

In particolare il costruttore dell’XmlSerializer prevede che venga dichiarata per quale classe stiamo costruendo il serializzatore, quindi possiamo utilizzare il metodo Serialize() per scrivere l’XML risultatnte nello stream o nel writer opportuno. La seguente funzione restituisce la stringa XML utilizzando uno StringWriter:

  1. Public Shared Function SerializzaXML(ByVal fattura As Fattura) As String
  2.     If fattura Is Nothing Then Throw New ArgumentNullException("Fattura")
  3.     Dim strXml As String = Nothing
  4.     Dim writer As New XmlSerializer(GetType(Fattura))
  5.     Using strWriter As New StringWriter()
  6.         writer.Serialize(strWriter, fattura)
  7.         strXml = strWriter.ToString()
  8.     End Using
  9.     Return strXml
  10. End Function

La seguente figura mostra la serializzazione di una fattura di prova:

image

Come possiamo osservare, tutte le proprietà della nostra classe vengono riportate all’interno dell’XML frutto della serializzazione. Ogni proprietà diventa un tag XML con il nome pari al nome della proprietà. Infine lo stato della fattura (definito come un’enumerazione) viene scritto come una stringa esattamente pari al valore dell’enumerazione impostato. A livello di codice, nel momento in cui viene eseguito il Serialize, vengono richiamati tutti i Get delle proprietà lettura/scrittura della classe (nel caso precedente non la proprietà Totale).

Di fatto, il comportamento visto in precedenza, è quello di default ma abbiamo la possibilità di intervenire per modificare il risultato dell’XML e lo possiamo fare utilizzando degli appositi attributi copntenuti nel namespace System.Xml.Serialization.

Se vogliamo, ad esempio, che una o più proprietà della nostra classe non finiscano all’interno dell’XML, possiamo utilizzare l’attributo XmlIgnoreAttribute decorando proprio la proprietà (o l’attributo) che non vogliamo finisca all’interno dell’XML.

Ad esempio, supponiamo di avere una proprietà della nostra fattura, chiamata Id, che non vogliamo serializzare. Potremo scrivere:

  1. <XmlIgnore()>
  2. Public Property Id As Integer?

In questo modo l’XML che si ottiene non ha il tag <Id>.

In maniera analoga, se vogliamo che una nostra proprietà non diventi un tag XML ma un attributo del tag Fattura, possiamo utilizzare l’attributo XmlAttribute indicando, eventualmente, il nome dell’attributo (altrimenti viene utilizzato il nome della proprietà):

  1. <XmlAttribute()>
  2. Public Property NumeroDocumento As String

E se volessimo che un tag XML non abbia il nome della proprietà ma un altro nome, allora potremmo utilizzare l’attributo XmlElement indicamndo il nome del tag:

  1. <XmlElement("Emissione")>
  2. Public Property DataEmissione As DateTime

Gli attributi contenuti nel namespace System.Serialization ci consentono, dunque di modificare il risultato della serializzazione a partire da quello di default.

Tutto ciò è utilissimo, non tanto quando siamo noi a gestire il gioco e definire lo schema dell’XML ma quando ci viene assegnato uno schema prestabilito e vogliamo creare un mapping a noi comodo con una classe da noi creata.

Vediamo, ora, la deserializzazione, ovvero il processo inverso della serializzazione, cioè quella procedura che ci permette di creare un oggetto a partire dall’XML.

L’XmlSerializer ci consente di deserializzare una stringa XML in un oggetto. In questo caso, anzichè un writer come supporto, dobbiamo utilizzare un reader:

  1. Public Shared Function DeserializzaXML(ByVal strFattura As String) As Fattura
  2.     Dim retObj As Fattura = Nothing
  3.     Dim reader = New XmlSerializer(GetType(Fattura))
  4.     Dim strReader = New StringReader(strFattura)
  5.     Try
  6.         retObj = CType(reader.Deserialize(strReader), Fattura)
  7.     Catch ex As Exception
  8.         Throw
  9.     End Try
  10.     Return retObj
  11. End Function

Ovviamente, se l’XML non è aderente allo schema, otteniamo un’eccezione nel momento in cui deserializziamo.

Ma cosa succede quando viene eseguite la deserializzazione?

Nel momento in cui viene richiamato il metodo Deserialize, viene istanziato l’oggetto di classe Fattiura (viene chiamato il costruttore) e, quindi, in sequenza vengono richiamati i set delle proprietà trovate all’interno dell’XML.

Per questo motivo, se non inseriamo un tag XML all’interno del file serializzato, la proprietà risultante conterrà il valore di default. Attenzione, quindi, a che le proprietà abbiano un valore di default coerente.

Nel prossimo post vedremo brevemente la serializzazione SOAP e, soprattutto, la serializzazione JSON.

Stay Tuned!!!!


 

Commenti

Post popolari in questo blog

VB.NET : Aggregare stringhe con LINQ

Tip facile facile, ma a qualcuno potrebbe servire. Supponiamo di avere una lista di stringhe (magari come risultato di una query LINQ) e di voler ottenere una stringa con la concatenazione delle stesse: Dim list = CreateList() Dim concatStr = (From s In list _ Select s).Aggregate( Function (currentString, nextString) currentString + nextString) MessageBox.Show(concatStr) Il metodo CreateList non ci interessa, in questo momento, ma crea una lista di oggetti String. Protected Function CreateList() As IEnumerable( Of String ) Dim list As String () = {" stringa1 ", " stringa2 ", " stringa3 ", " stringa4 ", " stringa5 "} Return list.AsEnumerable() End Function Questo metodo potrebbe restituire una qualsiasi lista di oggetti di cui, nella select successiva recuperiamo solo stringhe. La stessa tecnica è utilizzabile per concatenare stringhe inserendovi un carattere separatore Dim list = CreateList() Dim

VB.NET: SplashScreen con effetto fade-in

In questo post vorrei proporvi un modo per realizzare una splash screen per le nostre applicazioni Windows Form che appare progressivamente con un effetto fade. Supponiamo di avere il nostro progetto VB.NET in una soluzione Visual Studio 2008 in cui abbiamo il sorgente della nostra applicazione Windows Form. Inseriamo una splash screen utilizzando il menù Progetto->Aggiungi Nuovo Elemento e selezionando il tipo di elemento “Schermata Iniziale” A questo punto Visual Studio creerà, automaticamente, la schermata iniziale che possiamo personalizzare graficamente come vogliamo. Per poter fare in modo che questa finestra appaia nel momento in cui avviamo l’applicazione, è necessario aprire le proprietà del progetto e impostare la maschera di avvio: In questo modo, all’avvio dell’applicazione, la schermata appare immediatamente e scompare un attimo prima della visualizzazione della finestra dell’applicazione. Possiamo far apparire la schermata iniziale con un ef

VB.NET: Convertire un file DOC in RTF e PDF con office interop

In questo post vorrei proporvi del codice per poter convertire un file .doc in un file .rtf oppure .pdf utilizzando le API di interoperabilità di Office. Creeremo una classe, DocConverter, che esporrà le due funzionalità sopra citate. Cominciamo con il prevedere un attributo privato della classe che rappresenterà l’applicazione Word che utilizzeremo per la conversione. Creeremo l’istanza dell’attributo privato all’interno del costruttore della classe: Public Sub New () If Not CreateWordApp() Then Throw New ApplicationException(" Assembly di interoperabilità con Office non trovato! ") End If End Sub Private _wordApp As Word.ApplicationClass Protected Function CreateWordApp() As Boolean Dim retval = True Try _wordApp = New Word.ApplicationClass() _wordApp.Visible = False Catch ex As System.Exception _wordApp = Nothing retval = False End Try Return retval End Function La conve