WCF: Opzioni di serializzazione – Parte 2

Ci sono molti modi per serializzare i dati.
Come serializzarli dipende da un pò di fattori come: voler condividere tipi o contratti, supportare i tipi .NET esistenti etc

DataContractSerializer

E’ il meccanismo di serializzazione di default, si trova sotto il namespace System.Runtime.Serialization.
Viene usata per i contratti da condividere i tipi CLR vengono mappati su tipi definiti in XSD, in questa maniera otteniamo un’alta interoperabilità.
Ciò significa, ad esempio, che il tipo System.String di un’applicazione .NET diventerà java.lang.String in un’applicazione Java.

Quando dobbiamo condividere un tipo complesso utilizzeremo il decoratore [DataContract], per marcare il tipo da serializzare e [DataMember] per marcare i membri
e le proprietà.

Code Snippet
  1.     public class Employee
  2.     {
  3.         // ...
  4.         private int employeeID;
  5.         private string firstName;
  6.         private string lastName;
  7.         [DataMember]
  8.         public int EmployeeID
  9.         {
  10.             get { return employeeID; }
  11.             set { employeeID = value; }
  12.         }
  13.         [DataMember]
  14.         public string FirstName
  15.         {
  16.             get { return firstName; }
  17.             set { firstName = value; }
  18.         }
  19.         [DataMember]
  20.         public string LastName
  21.         {
  22.             get { return lastName; }
  23.             set { lastName = value; }
  24.         }
  25.     }

 

XSD Schema:

Code Snippet
  1. <GetDataResponse xmlns="http://tempuri.org/">
  2.   < GetDataResult xmlns:a="http://schemas.datacontract.org/2004/07/WcfService1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  3.     < a:EmployeeID>0</a:EmployeeID>
  4.     < a:FirstName i:nil="true" />
  5.     < a:LastName i:nil="true" />
  6.   </ GetDataResult>
  7. </ GetDataResponse>

 

XML dati ottenuti:

Code Snippet
  1. <GetDataResponse xmlns="http://tempuri.org/">
  2.   < GetDataResult xmlns:a="http://schemas.datacontract.org/2004/07/WcfService1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  3.     < a:EmployeeID>1</a:EmployeeID>
  4.     < a:FirstName>Salvo</a:FirstName>
  5.     < a:LastName>Di Fazio</a:LastName>
  6.   </ GetDataResult>
  7. </ GetDataResponse>

 

NetDataContractSerializer

Questo tipo di serializzazione viene usata quando cerchiamo un livello di fedeltà superiore tra client e server.
La classe NetDataContractSerializer ha un livello di fedeltà maggiore rispetto alla DataContractSerializer perchè, nella fase di serializzazione, vengono inseriti ulteriori informazioni inerenti
ai tipi CLR e alle reference; oltre a questo, tra le due, non vi è alcuna differenza.

Pertanto la NetDataContractSerializer può essere utilizzata solo se le estremità di serializzazione e deserializzazione condividono gli stessi tipi CLR.

Ecco un esempio di serializzazione:

Code Snippet
  1.         static void Main()
  2.         {
  3.             Employee e = new Employee { EmployeeID = 1, FirstName = "Salvo", LastName = "Di Fazio" };
  4.             FileStream fs = new FileStream("esempio.xml", FileMode.Create);
  5.             NetDataContractSerializer ser = new NetDataContractSerializer();
  6.             ser.WriteObject(fs, e);
  7.             fs.Close();
  8.         }

 

ed eccone il risultato inerente solamente all’oggetto scambiato:

Code Snippet
  1. <Employee z:Id="1" z:Type="ConsoleApplication1.ServiceReference1.Employee" z:Assembly="ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" xmlns="http://schemas.datacontract.org/2004/07/WcfService1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
  2.   < EmployeeID>1</EmployeeID>
  3.   < FirstName z:Id="2">Salvo</FirstName>
  4.   < LastName z:Id="3">Di Fazio</LastName>
  5. </ Employee>

XmlSerializer

Questo meccanismo di serializzazione è presente dal .NET 2.
Ci sono molti vantaggi nell’usare l’XmlSerializer: supporto per i tipi esistenti di .NET, compatibilità con gli ASP.NET Web Services e la creazione di un output XML da poter condividere.
WCF supporta l’XmlSerializer così da poter lavorare con i tipi esistenti a differenza del DataContractSerializer che è usato per i nuovi.

Si possono usare 3 approcci per lavorare con questa serializzazione:

  1. Quella di default, creando un oggetto e usando questo per scrivere i dati
  2. Usare gli attributi: [XmlElement] e [XmlAttribute] (e altri attributi)
  3. Usare l’interfaccia IXmlSerializable per customizzare tutto il processo di serializzazione

Ecco un esempio:

Code Snippet
  1.     public class Employee
  2.     {
  3.         // ...
  4.         private int employeeID;
  5.         private string firstName;
  6.         private string lastName;
  7.         public int EmployeeID
  8.         {
  9.             get { return employeeID; }
  10.             set { employeeID = value; }
  11.         }
  12.         public string FirstName
  13.         {
  14.             get { return firstName; }
  15.             set { firstName = value; }
  16.         }
  17.         public string LastName
  18.         {
  19.             get { return lastName; }
  20.             set { lastName = value; }
  21.         }
  22.     }
Code Snippet
  1.         static void Main()
  2.         {
  3.             Employee e = new Employee { EmployeeID = 1, FirstName = "Salvo", LastName = "Di Fazio" };
  4.             FileStream fs = new FileStream("esempio.xml", FileMode.Create);
  5.             XmlSerializer ser = new XmlSerializer(typeof(Employee));
  6.             ser.WriteObject(fs, e);
  7.             fs.Close();
  8.         }

 

Senza la classe XmlSerializer vista la nuova implementazione di Employee, questa non sarebbe serializzabile.
L’attributo [XmlSerializerFormat] può essere usato per obbligare WCF ad usare l’XmlSerializer:

Code Snippet
  1.     [ServiceContract]
  2.     [XmlSerializerFormat]
  3.     public interface IEmployeeXml
  4.     {
  5.         [OperationContract]
  6.         Employee GetData();
  7.     }

DataContractJsonSerializer

Supporta l’uso di JavaScript Object Notation (JSON).
Questo tipo di serializzazione è ottima se voltete chiare il vostro metodo WCF da una Web Application che utilizza AJAX o Silverlight.
Viene usata quando abilitiamo WebScriptEnablingBehavior o WebHttpBehavior e configurato l’encoding JSON.
Quando gli endpoint sono così configurati, istruiscono WCF a supportare servizi di tipo REST/POX.

Code Snippet
  1.         static void Main()
  2.         {
  3.             Employee e = new Employee { EmployeeID = 1, FirstName = "Salvo", LastName = "Di Fazio" };
  4.             FileStream fs = new FileStream("esempio.xml", FileMode.Create);
  5.             DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Employee));
  6.             ser.WriteObject(fs, e);
  7.             fs.Close();
  8.         }

 

il risultato sarà:

Code Snippet
  1. {"EmployeeID":1,"FirstName":"Salvo","LastName":"Di Fazio"}