Home Page Home Page Articoli WCF Windows Communication Foundation - Serializzazione

WCF Windows Communication Foundation - Serializzazione

La serializzazione è un processo di "trasformazione" degli oggetti molto utilizzato in .NET, fin dalla prima versione. In questo articolo approfondiremo il suo utilizzo all'interno del WCF e vedremo le possibilità che esso ci offre in questo contesto.
Autore: Giovanni Ferron Livello:

Serializzazione – Introduzione


Prima della pratica un po' di teoria non guasta mai. Serializzazione significa conversione/trasformazione, infatti un oggetto, con le sue proprietà e metodi, viene convertito in un flusso XML o in Binario per poter essere archiviato (su un media esempio su disco) o trasportato (su una rete/network). Visto che stiamo parlando di servizi consumabili via rete la serializzazione che più si adatta al modello in questione è quella XML, un flusso standard ed elaborabile da qualsiasi applicazione, indipendentemente dalla piattaforma; Ad esempio possiamo serializzare un oggetto e trasportarlo da client a server per mezzo del protocollo HTTP. La classe Principale è la XmlSerializer di cui i metodi più importanti sono:

- Serialize (che trasforma il nostro oggetto in XML)
- Deserialize (che riconverte l'XML in 'oggetto)

N.B. Iniziamo subito a fornire alcuni link della guida in linea dove trovate alcuni nomi di classi che utilizzeremo in questo articolo. Per ciò che riguarda la serializzazione i namespaces di riferimento con relative sottoclassi sono i seguenti:

- System.Runtime.Serialization 
- System.Xml.Serialization 

Non tutti gli oggetti possono essere serializzati in formato XML, in questi casi se si vuole comunque trasportare l'oggetto è necessario utilizzare la serializzazione binaria, perdendo in compatibilità tra sistemi.Per controllare la serializzazione di un oggetto si utilizzano degli attributi, ad esempio:

Codice .NET n°1
[Serialize]
public class Utente
{
[XmlElement]
public string Nome{}
}


In questo caso abbiamo dichiarato la classe Utente serializzabile, e la proprietà Nome come un elemento del nostro XML. Se serializzassimo questo oggetto la rappresentazione XML sarebbe simile alla seguente:

Codice XML n°2
<Utente>
<Nome>Nome utente</Nome>
</Utente>


possiamo anche cambiare il nome del nostro elemento secondo le nostre esigenze, utilizzando l'attributo ElementName per XmlElement, riprendendo l'esempio di prima:

Codice .NET n°3
[Serialize]
public class Utente
{
[XmlElement(ElementName=“Name”)]
public string Nome{}
}


ed avrà un output di questo tipo:

Codice XML n°4
<Utente>
<Name>Nome utente</Name>
</Utente>


Come avrete notato l'elemento/nodo Nome si è trasformato in Name, questo ci da la possibilità di creare un livello ulteriore di astrazione rispetto alla nostra classe.

Serializable


[Serializable] è il più utilizzato e conosciuto dei metodi di serializzazione, infatti basta associare alla nostra classe l'attributo, permettendoci di trasformarla in XML o in Binary, ecco un esempio:

Codice .NET n°5
[Serializable]
public class Persona
{
...
public string Nome
{
get { ... }
set { ... }
}
...
}


Particolarità dell'attributo [Serializable] è che ogni elemento, sia pubblico che privato, viene serializzato. Se vogliamo ottenere il contrario dobbiamo utilizzare l'attributo [NonSerialized]. Utilizzando questo metodo abbiamo la possibilità di utilizzare la nostra classe serializzata anche per altri scopi, ad esempio per serializzare in binario la nostra classe, oltre a distribuirla attraverso il WCF, con la classe BinaryFormatter.

XMLSerialization


La serializzazione XML non è una novità del .NET Framework 3.5, infatti era già utilizzata nelle versioni precedenti nei Web Services ASP.NET, tutto questo per semplificare il lavoro a chi ha sviluppato molti web service e vuole implementarli in WCF. Ecco la nostra classe Persona con gli attributi per l'XMLSerialize:

Codice .NET n°6
[XmlRoot("Persona",Namespace="urn:Persona-com")]
public class Persona
{
...
[XmlAttribute("Nome")]
public string Name
{
get { ... }
set { .. }
}
...
}


Come si può notare la classe che desidero serializzare in XML ha assegnato l'attributo [XmlRoot] che identifica la root del nostro XML, e ad ogni elemento che voglio rendere disponibile nel mio file XML viene impostato l'attributo [XmlAttribute].
WCF automaticamente provvederà a serializzare e deserializzare la nostra classe, però visto che la serializzazione di default è quella del DataContract, è necessario specificare nel nostro messaggio il tipo di engine per la deserializzazione, ecco perché nel nostro ServiceContract specifichiamo l'attributo [XmlSerializerFormat], in questo modo:

Codice .NET n°7
[ServiceContract]
[XmlSerializerFormat]
interface PeopleService
{
...
}


A questo punto il nostro client può creare una referenza al servizio, creando una ServiceReference nel nostro progetto client e stanziare un oggetto Proxy per interrogare i metodi del nostro ServiceContract, ad esempio:

Codice .NET n°8
//csharpHostService è il nome della referenza al servizio
csharpHostService.PeopleServiceClient client = new csharpClient.csharpHostService.PeopleServiceClient();

//Metodo che inserisce una nuova persona
client.AddPerson("Pippo", "Pluto", "Indirizzo");

//Oggetto serializzato Persona
csharpHostService.Persona _person = client.GetPerson("Pippo");
Console.WriteLine("Utente {0} inserito", _person.Nome);


DataContract


La dichiarazione del DataContract altro non è che una forma di serializzazione ad hoc di WCF, infatti utilizza un engine chiamato "Data Contract Serializer" che si preoccupa della serializzazione e deserializzazione degli oggetti. Ecco come è definito un DataContract:

Codice .NET n°9
[DataContract]
public class Person
{
...
[DataMember]
public string Name
{
get { ... }
set { ...}
}
...
}


Come potete notare alla classe viene assegnato l'attributo [DataContract] che la identifica come serializzabile, mentre ad ogni membro della classe che vogliamo rendere pubblico attraverso il servizio deve essere assegnato l'attributo [DataMember]. Con questi due semplici attributi il nostro Custom Type è pronto, ma le classi DataContractAttribute e DataMemberAttribute ci offrono una serie di opzioni per customizzare ancora di più il processo di serializzazione.

DataContractAttribute
- Name: Nome della classe serializzata, questo ci permette di impostare il nome che desideriamo per la classe, per esempio rendere pubblica la classe Person sotto falso nome, ad esempio Persona.
- Namespace: Nome del namespace che verrà utilizzato nell'xml serializzato nel caso in cui abbiamo esigenze particolari in integrazione di applicazioni.

DataMemberAttribute
- Name: Nome del membro della classe, come per il DataContract possiamo definire un nome diverso da quello della proprietà, ad esempio da Name e Nome
- Order: Definisce l'ordine in cui i membri vengono serializzati.
- IsRequired: Indica se il membro deve essere presente obbligatoriamente alla deserializzazione dell'oggetto
- EmitDefaultValue: Omette la scrittura di un membro se il suo valore equivale a quello di default.

Con queste proprietà il nostro codice lo possiamo trasformare in:

Codice .NET n°10
[DataContract(Name="Persona", Namespace="urn:persona-com")]
public class Person
{
...
[DataMember(Name="Nome",Order=2)]
public string Name
{
get { ... }
set { ... }
}
...
}


In questo caso il client potrà utilizzare come tipo di dati una classe Persona che avrà tra le sue proprietà una denominata Nome, ad esempio:

Codice .NET n°11
//csharpHostService è il nome della referenza del servizio
csharpHostService.Persona _person = new csharpHostService.Persona();
_person.Nome = “pippo”;
Console.WriteLine(_person.Nome);


Di seguito una serie di tipi che sono supportati dal DataContract

- Tipi di dati del CLR
- Array di Byte, DateTime, TimeSpan, GUID, Uri, XmlQualifiedName, XmlElement e Array XmlNode
- Enum
- Tipi con attributo DataContract o attributo CollectionDataContract
- Tipi di dati che implementano l'interfaccia IXmlSerializable
- Array e Collection, incluse List, Dictionary e Hashtable
- Tipi con l'attributo Serializable e inclusi quelli che implementano l'interfaccia ISerializable.

NetDataContractSerializer


Piccolo accenno a questo metodo di serializzazione. Questo engine supporta gli attributi [Serializable] e [DataContract], con tutti gli annessi e connessi a questi due engine. Al contrario degli due metodi invece non è necessario specificare degli attributi sulla nostra classe per permetterne la serializzazione, questo però comporta che funziona solo nel caso in cui il client sia Microsoft (era intuibile dal nome).
Visto che non dobbiamo modificare il DataContract, l'unica parte di codice che ci interessa risiede nel ServiceContract, aggiungendo l'attributo [NetDataContract] ai metodi che vogliamo esporre.

Codice .NET n°12
[ServiceContract]
interface PeopleService
{
...
[OperationContract]
[NetDataContract]
Person GetPerson(string name);
...
}


Da notare il fatto che Microsoft non incoraggia l'utilizzo di questo tipo di serializzazione, infatti per poterla abilitare è necessario specificare un Behavior che ne permetta l'utilizzo.

Generazione da Schema XSD


Visto che a Microsoft stanno a cuore le nostre ore lavorative, ha pensato di fornirci un tool per la creazione automatica dei DataContract partendo da uno schema XSD, il tool in questione si chiama svcutil.exe. Questa applicazione ha un infinità di opzioni (basta guardare l'help) ma quella che a noi interessa è lo switch /dconly. Prendiamo ad esempio un semplice schema

Codice XML n°13
<?xml version=”1.0” encoding=”utf-8” ?>
<xs:schema id=”XMLSchema1”>
<xs:complexType name=”Person”>
<xs:sequence>
<xs:element name=”Nome” type=”xs:string” />
<xs:element name=”Cognome” type=”xs:string” />
</xs:sequence>
</xs:complexType>
<xs:element name=”Persona” type=”mstns:Person” />
</xs:schema>


In questo caso abbiamo definito un tipo di dati Person che ha due proprietà, Nome e Cognome, e abbiamo creato un elemento Persona di tipo Person.
A questo punto eseguiamo il nostro tool eseguendo da dos il comando

svcutil.exe [path schema XSD] /dconly [/language:C#] o [/language:VB]

Automaticamente il nostro tool ci genererà un file .cs con al suo interno il nostro DataContract e i DataMember, file .cs che possiamo includere senza problemi nel nostro progetto.

Conclusioni


In questo articolo abbiamo esplorato le varie possibilità di serializzazione attraverso il Windows Communication Foundation, tra le più importanti XmlSerializer e DataContract. Il Framework ci mette a disposizione anche in questo caso diversi strumenti utili, per poter sviluppare nuove applicazioni e/o integrarne di vecchie con grande facilità e minori sprechi di tempo.
Voto medio articolo: Numero Voti: 0

File allegati


WCFSerialization.zip (326 Kbyte)
Giovanni Ferron

Giovanni Ferron

Sviluppatore dal 2000. Collabora a grandi progetti nella creazione di portali e intranet aziendali. Attualmente ha lasciato la terra natia per una nuova avventura in Australia, dove lavora come programmatore web per una emittente radio Australiana. Profilo completo

Articoli collegati

WCF Windows Communication Foundation - Overview
Questa introduzione è la prima parte di una serie di articoli su un componente chiave del .NET Framework 3.5 il Windows Communication Foundation (WCF). Vediamo che cos'è e come funziona.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 3
Windows Longhorn Refresh - Build #4074 Screenshots
Come annunciato poco più sopra nelle news è stata resa disponibile da Microsoft una nuova Build di Windows Longhorn la 4074 per l'esattezza. Ci sono alcune novità, sono stati apportati miglioramenti significativi in alcune aree e sono state implementate nuove funzionalità. Vediamo in questo articolo che cosa è cambiato.
Autore: David De Giacomi | Difficoltà: | Commenti: 3 | Voto:
Anteprima Windows Longhorn, Architettura, WinFS (parte 1)
Nella prima parte di questo articolo faremo una dettagliata introduzione relativa a Windows Longhorn, per capire che cos'è, come funziona e come è stato progettato. Successivamente mostreremo il nuovo e potentissimo File System WinFS descrivendone le caratteristiche principali.
Autore: David De Giacomi | Difficoltà: | Commenti: 2
Windows Longhorn, Internet Explorer, Avalon e considerazioni (parte 2)
In questa seconda parte, più ricca di screenshots vedremo le modifiche e i miglioramenti apportati ad Internet Explorer e al sistema operativo in generale. Ci sarà una breve introduzione su Avalon e alcune immagini vi mostreranno come sarà la GUI di Windows del futuro.
Autore: David De Giacomi | Difficoltà: | Voto:
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5