laborator 05 - serializare
DESCRIPTION
c#TRANSCRIPT
111/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
SerializareSerializare5
211/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Ce este serializarea?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.
311/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Ce este serializarea?Ce este serializarea?
411/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Cum serializam un obiect?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();
511/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Cum deserializam un Cum deserializam un obiect?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();
611/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Cum cream clase ce pot fi Cum cream clase ce pot fi serializate?serializate? Pentru ca o clasa sa fie serializabila
trebuie adaugat atributul [Serializable] la clasa.
Putem controla serializarea si deserializarea pentru a obtine rezultatele dorite.
711/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
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; } }
811/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Cum oprim serializarea Cum oprim serializarea unor anumiti membri?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.
911/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
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; } }
1011/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
VersionareVersionare 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.
1111/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
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; } }
1211/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
VersionareVersionare 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.
1311/26/07L4 .NET ADF - (C) Victor Adrian Prisacariu
Alegerea unui format de Alegerea unui format de serializareserializare 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.
1411/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Alegerea unui format de Alegerea unui format de serializareserializare 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.
1511/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
SOAPFormatterSOAPFormatter 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 .
1611/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Serializare XMLSerializare 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
1711/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Cand folosim serializare Cand folosim serializare XML?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
1811/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Cum serializam XML un Cum serializam XML un obiect?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();
1911/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Cum deserializam XML un Cum deserializam XML un obiect?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();
2011/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Cum cream clase ce pot fi Cum cream clase ce pot fi serializate XML?serializate XML? Conditiile pe care trebuie sa le
indeplineasca o clasa pentru a fi serializabila XML sunt: clasa trebuie sa fie publica tot 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
2111/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Controlul formatului Controlul formatului fisierului XML de iesirefisierului 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
2211/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
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>
2311/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Controlul formatului Controlul formatului fisierului XML de iesirefisierului 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.
2411/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
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>
2511/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
XML SchemaXML 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.
2611/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
XML SchemaXML 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
2711/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Serializare customSerializare 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.
2811/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Cum implementam o Cum implementam o serializare custom?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.
2911/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Cum implementam o Cum implementam o serializare custom?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
3011/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
[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); } }
3111/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Evenimente in serializareEvenimente in serializare Atunci cand folositi BinaryFormatter .NET framework poate declansa
anumite evenimente in diferite momente ale procesului de serializare.
Serializare incepe
Serializare incepe [OnSerializing][OnSerializing]
Se face serializarea propriu-zisa
Se face serializarea propriu-zisa
[OnSerialized][OnSerialized]Serializarea s-a terminat
Serializarea s-a terminat
3211/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
Evenimente in Evenimente in deserializaredeserializare
Deserializarea incepe
Deserializarea incepe
[OnDeserializing]
[OnDeserializing]
Deserializarea are loc
Deserializarea are loc
IDeserializationCallback.
OnDeserialization
IDeserializationCallback.
OnDeserialization
[OnDeserialized]
[OnDeserialized]
Deserializarea s-a terminat
Deserializarea s-a terminat
3311/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
EvenimenteEvenimente 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; }
3411/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
StreamingContextStreamingContext 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
3511/26/07L3 .NET ADF - (C) Victor Adrian Prisacariu
StreamingContextStreamingContext 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.