Sunteți pe pagina 1din 35

5

Serializare

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 1


Ce este serializarea?
 Serializarea este procesul prin care convertim un
obiect intr-o secventa liniara de bytes (octeti) care
poate fi stocata sau transferata.
 Deserializarea este procesul invers serializarii.

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 2


Ce este serializarea?

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 3


Cum serializam un obiect?
 PAS1: Cream un stream spre care vom directiona
serializarea.
 PAS2: Cream un obiect BinaryFormatter
 PAS3: Folosim metoda BinaryFormatter.Serialize

 ex:
 string data = “data de salvat”;
 FileStream fs = new FileStream (“data.out”,
FileMode.Create);
 BinaryFormatter bf = new BinaryFormatter();
 bf.Serialize(fs,data);
 fs.Close();
11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 4
Cum deserializam un obiect?
 PAS1: Cream un stream din care vom citi
 PAS2: Cream un obiect BinaryFormatter
 PAS3: Cream un obiect in care vom salva datele deserializate
 PAS4: Apelam metoda BinaryFormatter.Deserialize

 ex:
 FileStream fs = new FileStream(“data.out”, FileMode.Open);
 BinaryFormatter bf = new BinaryFormatter();
 string data = (string)bf.Deserialize(fs);
 fs.Close();

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 5


Cum cream clase ce pot fi
serializate?
 Pentru ca o clasa sa fie serializabila trebuie
adaugat atributul [Serializable] la clasa.
 Putem controla serializarea si deserializarea

pentru a obtine rezultatele dorite.

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 6


 ex:
 [Serializable]
 class ObiectCumparat
{
 public int productID;
 public decimal pret;
 public int cantitate;
 public decimal total;

 public ObiectCumparat(int productID, decimal pret, int
cantitate)
 {
 this.productID = productID;
 this.pret = pret;
 this.cantitate = cantitate;
 total = pret*cantitate;
 }
}
11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 7
Cum oprim serializarea unor
anumiti membri?
 Observam ca variabila total este calculata prin inmultirea
valorilor pret si cantitate, deci stocarea sa pe disc este inutila
si va ocupa spatiu suplimentar.
 Putem in schimba sa actualizam aceasta variabila dupa
deserializare.
 Pentru a realiza acest lucru platforma .NET contine:
 atributul [NonSerialized] pe care il punem inaintea definiri
variabilei si care va instrui serializatorul sa nu o serializeze
 interfata IDeserializationCallback ce contine metoda
IDeserializationCallback.OnDeserialization ce va fi apelata cand
se termina deserializarea.

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 8


 clasa ObiectCumparat devine:
 [Serializable]
 class ObiectCumparat: IDeserializationCallback
 {
 public int productID;
 public decimal pret;
 public int cantitate;
 [NonSerialized] public decimal total;

 public ObiectCumparat(int productID, decimal pret, int cantitate)
 {
 this.productID = productID;
 this.pret = pret;
 this.cantitate = cantitate;
 total = pret*cantitate;
 }

 void IDeserializationCallback .OnDeserialization(Object sender)


 {
 total = price * cantitate;
 }
 }

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 9


Versionare
 O problema ce poate sa apara la serializare este
compatibilitatea cu versiunile anterioare. Daca versiunea
1.0 a aplicatiei noaste foloseste un format de clasa si
versiunea 1.1 mai adauga un camp ce va fi
serializat/deserializat pot sa apara probleme.
 Pentru a rezolva problema putem folosi atributul
[OptionalField] pt. membrii noi adaugati.
 Acesta nu afecteaza procesul de serializare. La
deserializare daca nu va fi gasit in streamul de intrare
runtime-ul nu va da eroare dar va seta valoarea variabilei
optionale ca null sau valoarea default pentru tipul
respectiv.
11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 10
 In versiunea 1.1 a clasei ObiectCumparat aceasta va avea urmatoarea forma:

 [Serializable]
 class ObiectCumparat: IDeserializationCallback
 {
 public int productID;
 public decimal pret;
 public int cantitate;
 [NonSerialized] public decimal total;
 [OptionalField]public int taxe;

 public ObiectCumparat(int productID, decimal pret, int cantitate)


 {
 this.productID = productID;
 this.pret = pret;
 this.cantitate = cantitate;
 total = pret*cantitate;
 }

 void IDeserializationCallback .OnDeserialization(Object sender)


 {
 total = price * cantitate;
 }
 }

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 11


Versionare
 Sfaturi pentru o versionare corecta:
 Nu eliminati niciodata un camp serializat dintr-o
versiune mai noua
 Niciodata nu aplicati atributul NotSerialized la o
variabila la care nu era aplicat in o versiune anterioara
 Cand adaugati un camp nou declarati-l optional.
 Cand stergeti atributul NotSerialized adaugati atributul
OptionalField
 Initializati la deserializare toate campurile optionale cu
valori folositoare pentru aplicatia voastra.
11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 12
Alegerea unui format de
serializare
 Platforma .NET include mai multe metode de
formatare a datelor serializate:
 BinaryFormatter: cea mai eficienta metoda de
serializare date in .NET
 SoapFormatter: format bazat pe XML folositor pentru
schimbul in retea de fisiere. Are sanse mai mari sa
treaca de firewall-uri decat BinaryFormatter.

11/26/07 L4 .NET ADF - (C) Victor Adrian Prisacariu 13


Alegerea unui format de
serializare
 In general este recomandat sa folositi
BinaryFormatter cand stiti ca toate aplicatiile ce
vor deserializa sunt construite folosind
platforma .NET.
 Folositi SOAPFormatter atunci cand doriti sa

trimiteti datele serializate prin retea.

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 14


SOAPFormatter
 Pentru a folosi SOAPFormatter procedati exact ca la
BinaryFormatter.

 ex:
 FileStream fs = new FileStream(“data.in”,
FileMode.Open);
 SOAPFormatter bf = new SOAPFormatter();
 string data = (string)bf.Deserialize(fs);
 fs.Close();
 Pentru a obtine compatibiliate maxima intre aplicatia voastra si
alte aplicatii ce vor deserializa datele puteti folosi atribute prin
care sa controlati formatul datelor scrise in stream-ul de iesire.
Pentru mai multe detali cititi la pagina 280 in cartea .NET .
11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 15
Serializare XML
 XML este un format standardizat, bazat pe text, pentru
stocarea unor informatii ce pot fi citite usor de aplicatii.
 XML foloseste un format de organizare a datelor de tip
arborescent.
 XML poate fi folosit pentru stocarea oricarui tip de date
inclusiv documente, imagini, filme, muzica, etc.
 .NET framework ofera mai multe biblioteci pentru citire
si scriere fisiere XML

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 16


Cand folosim serializare XML?
 Este recomandat sa folositi serializarea XML atunci
cand doriti interoperatibilitate, mai exact atunci cand
doriti ca fisierele produse sau modificate de aplicatia
voastra sa fie usor citibile de aplicatii ce nu sunt scrise in
.NET
 In consecinta serializare XML are urmatoarele avantaje:
 Interoperatibilitate mai mare
 Fisierele pot fi editate usor cu editoare normale text
 Versionare mai usoara

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 17


Cum serializam XML un obiect?
 PAS1: Crearea unui stream care va tine obiectul serializat (sau a
unui TextWriter sau a unui XmlWriter)
 PAS2: Crearea unui obiect XmlSerializer ce va primi ca parametru
la constructor un tipul obiectului pe care il vom serializa
 PAS3: Apelarea metodei XmlSerializer.Serialize

 ex:
 FileStream fs = new FileStream(“data.out”,FileMode.Create);
 XmlSerializer xmls = new XmlSerializer(typeof(DateTime));
 xmls.Serialize(fs,DateTime.Now);
 fs.Close();

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 18


Cum deserializam XML un
obiect?
 PAS1: Creare stream de unde vom citi datele serializate
 PAS2: Creare obiect XmlSerializer (cu parametru la constructor
tipul obiectului de deserializat)
 PAS3: Apelarea metodei XmlSerializer.Deserialize

 ex:
 FileStream fs = new FileStream(“data.out”,FileMode.Create);
 XmlSerializer xmlDs = new XmlSerializer(typeof(DateTime));
 DateTime dataTrecuta = (DateTime)xmlDs.Deserialize(fs);
 fs.Close();

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 19


Cum cream clase ce pot fi
serializate XML?
 Conditiile pe care trebuie sa le indeplineasca o
clasa pentru a fi serializabila XML sunt:
 clasa trebuie sa fie publica
 toti membrii serializati trebuie sa fie publici
 clasa trebuie sa aiba un constructor fara parametri
 nu trebuie sa aiba atributul Serializable
 membri privati sau protected vor fi sariti la serializare

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 20


Controlul formatului fisierului
XML de iesire
 Daca dorim interoperatibilitate cu alte limbaje de
programare uneori este necesara schimbarea
formatului in care se va scrie sau citi fisierul XML.
 Aceasta schimbare se face prin diferite atribute aplicate
membrilor clasei ce va fi serializata/deserializata

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 21


 public class ObiectCumparat
 {
 public int productID;
 public decimal pret;
 public int cantitate;
 public decimal total;

 public ObiectCumparat()
 {
 }
 }

 Fisierul XML rezultat dupa serializare va avea urmatorul continut:


 <?xml version 1.0>
 <ObiectCumparat>
 <productID>100</productID>
 <pret>1000</pret>
 <cantitate>10</cantitate>
 <total>1212</total>
 </ObiectCumparat>

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 22


Controlul formatului fisierului
XML de iesire
 Exemple de atribute (pentru o lista completa vedeti
pagina 293 din cartea .NET ADF):
 XmlAttribute: Membrul va fi serializat ca atribut XML
 XmlElement: Membrul va fi serializat ca un element XML
 XmlIgnore: Membrul va fi ignorat
 XmlRoot: Este folosit pentru a specifica optiuni despre
namespace si numele elementului
 Daca atributele nu sunt suficiente pentru a obtine
formatul dorit, puteti creea propriul serializator XML
implementand IXmlSerializable cu metodele ReadXml
si WriteXml.
11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 23
 ex:
 [XmlRoot(“ObiectDeCumparat”)
 public class ObiectCumparat
 {
 [XmlAttribute] public int productID;
 public decimal pret;
 public int cantitate;
 [XmlIgnore] public decimal total;

 public ObiectCumparat()
 {
 }
 }

 <?xml version 1.0>


 <ObiectDeCumparat productID=“100”>
 <pret>1000</pret>
 <cantitate>10</cantitate>
 </ObiectDeCumparat>

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 24


XML Schema
 Atunci cand 2 aplicatii schimba intre ele fisiere XML,
acestea respecta in general o anumita maniera de
organizare numita schema. Pentru mai multe info
despre Xml schema: http://www.w3.org/XML/Schema
 .NET framework contine o aplicatie ce genereaza
automat clase dupa o anumita schema (xsd.exe).Cand
veti instantia o astfel de clasa fisierul XML generat din
ea va respecta schema respectiva. E o metoda mai
simpla si typesafe de a parsa si a scrie un document
XML care sa respecte un anumit format.

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 25


XML Schema
 Pentru a genera o clasa bazata pe o schema:
 PAS1: Creati sau copiati schema (fisierul .xsd)
 PAS2: Deschideti Visual Studio 2005 Command Prompt
 PAS3: Rulati comanda:
 xsd C:\schema\library.xsd /classes /language:CS
 PAS4: Folositi clasa nou creata (Schema.cs) in aplicatia
voastra

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 26


Serializare custom
 Serializare custom este procesul prin care
controlati complet mecanismul de serializare si
deserializare a unui obiect.
 Puteti realiza o interoperatibilitate mai mare si o

versionare mai buna folosind serializarea custom.

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 27


Cum implementam o serializare
custom?
 Puteti modifica mecanismul .NET de serializare/deserializare
mostenind interfata ISerializable si aplicand atributul Serializable
la clasa.
 Mostenirea clasei ISerializable inseamna implementarea
metodelor GetObjectData si a unui constructor special care va fi
folosit la deserializare.
 Runtime-ul va apela metoda GetObjectData la serializare si acel
constructor la deserializare.
 Compilatorul va va avertiza daca nu ati implementat
GetObjectData, dar daca nu ati implementat constructorul doar
la runtime se va arunca o exceptie la deserializare.

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 28


Cum implementam o serializare
custom?
 Metoda GetObjectData trebuie sa completeze un
obiect de tip SerializationInfo cu datele pe care
doriti sa le serializati din clasa.
 Tot ce trebuie sa faceti este sa adaugati valorile de

serializat ca perechi nume/valoare (ca la o


colectie) folosind metoda AddValue
 Metoda AddValue creeaza intern un obiect de tip

SerializationEntry
11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 29
 [Serializable]
 class ObiectCumparat : ISerializable
 {
 public int productID;
 public decimal pret;
 public int cantitate;
 [NonSerialized] public decimal total;

 protected ObiectCumparat(SerializationInfo info, StreamingContext context)
 {
 this.productID = info.GetInt32(“Product ID”);
 this.pret = info.GetDecimal(“Pret”);
 this.cantitate = info.GetInt32(“Cantitate”);
 this.total = pret*cantitate;
 }

 [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)]
 public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
 {
 info.AddValue(“Product ID”,productID);
 info.AddValue(“Pret”,pret);
 info.AddValue(“Cantitate”,cantitate);
 }
 }

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 30


Evenimente in serializare
 Atunci cand folositi BinaryFormatter .NET framework poate declansa
anumite evenimente in diferite momente ale procesului de serializare.

Se face serializarea
Serializare incepe [OnSerializing]
propriu-zisa

Serializarea s-a
[OnSerialized]
terminat

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 31


Evenimente in deserializare
Deserializarea Deserializarea are
[OnDeserializing]
incepe loc

IDeserializationCall
Deserializarea s-a
[OnDeserialized] back.
terminat
OnDeserialization

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 32


Evenimente
 Pentru a putea raspunde la aceste evenimente trebuie
sa construiti metode ce primesc ca parametru un
StreamingContext, au ca atribut tipul de eveniment la
care raspund si nu returneaza nimic:
 ex:
 [OnDeserializing]
 void CalculareTotal(StreamingContext sc)
{
 total = pret*cantitate;
}
11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 33
StreamingContext
 Obiectul StreamingContext este folositor atunci cand
doriti o serializare/deserializare diferita in functie de
destinatia obiectului.
 ex: in general nu e nevoie sa serializati informatii
despre procesul in curs pentru ca ele vor fi invechite la
deserializare. Totusi daca deserializatorul este chiar
procesul in curs aceasta pot fi foarte folositoare
 Aceasta informatie este stocata in StreamingContext

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 34


StreamingContext
 StreamingContext are 2 proprietati:
 Context: o referinta la un obiect care contine orice
informatie dorita de programator legata de informatiile de
context
 State: un set de biti care indica sursa sau destinatia
obiectelor serializate sau deserializate
 File: sursa sau destinatia este un fisier
 CrossProcess: sursa sau destinatia este alt proces pe aceeasi
masina
 CrossMachine: sursa sau destinatia este alt proces pe alta
masina
 etc.

11/26/07 L3 .NET ADF - (C) Victor Adrian Prisacariu 35

S-ar putea să vă placă și