10. diel - Serializácia a deserializácia v C# .NET
V predchádzajúcej lekcii, LINQ to XML v C# .NET, sme sa naučili generovať, čítať, editovať a mazať dáta v XML súboroch pomocou technológie LINQ to XML.
V kurze C# .NET budeme konvertovať objekt na prúd bytov, ktorý prevedieme späť na kópiu objektu. Naučíme sa teda serializovať a deserializovať objekt.
Úvod do serializácie a deserializácie
Serializácia je uchovanie stavu objektu. Trochu odbornejšie by sa to dalo popísať ako konvertovanie objektu na prúd bytov a potom uloženie niekde do pamäte, databázy alebo súboru. Deserializácia je opak serializácie. Dalo by sa povedať, že prevedieme prúd bytov späť na kópiu objektu.
Využitie
Serializácia nám umožňuje uložiť stav objektu a potom pomocou deserializácie si ho kedykoľvek znova vytvoriť. Pomocou serializácie sa napríklad posielajú dáta cez sieť alebo sa ukladá nastavenie aplikácie.
Serializácia
Než sa pustíme do vlastnej konverzie objektu na prúd bytov, pripravíme si
aplikáciu. Vytvorme si aplikáciu typu Windows Forms
Application s názvom SerializationSample.
Trieda User
Do aplikácie si pridáme túto verejnú triedu
User, ktorej inštancie budeme chcieť zachovať:
[Serializable()] public class User { [XmlAttribute("FirstName")] public string FirstName { get; set; } [XmlAttribute("LastName")] public string LastName { get; set; } [XmlAttribute("BirthDate")] public DateTime BirthDate { get; set; } public override string ToString() { return "First name: " + FirstName + "Last name: " + LastName + "Birth date: " + BirthDate.ToShortDateString(); } }
Triedu anotujeme atribútom [Serializable()], ktorým hovoríme,
že jej inštancie budeme chcieť serializovať. Ďalej pridáme vlastnosti:
FirstName,LastName,BirthDate.
Všetky vlastnosti anotujeme atribútom [XmlAttribute("Name")],
ktorý zmení XML element z párového na nepárový a hodnota danej vlastnosti
bude v atribúte Name. Napríklad
<User FirstName="John"> namiesto
<FirstName>John</FirstName>. Nakoniec prepíšeme
metódu ToString().
Keby sme mali v triede vlastnosť, ktorú by sme nechceli
serializovať, anotovali by sme ju atribútom [XmlIgnore].
Hlavný formulár
Ukážme si podobu hlavného formulára, ktorý si vzápätí popíšeme:

Na hlavný formulár si pridáme:
- Dva prvky
TextBoxs názvomfirstNameTextBoxalastNameTextBoxna meno a priezvisko. - Prvok
DateTimePickers názvombirthDateDateTimePickerpre dátum narodenia. - Tlačidlo s názvom
addButtonna pridanie používateľa do našej aplikácie. - Prvok
ListBoxs názvomusersListBoxna zobrazenie používateľov.
Ovládacie prvky sme si premenovali z vygenerovaných názvov na také názvy, v ktorých sa vyznáme.
Kód hlavného formulára
Presunieme sa do kódu hlavného formulára, kam budeme písať všetok ďalší kód.
Kolekcia používateľov
Pred vygenerovaným konštruktorom si vytvoríme privátnu kolekciu
users typu List<User>:
private List<User> users = new List<User>();
Obslužná metóda prvku
addButton
Presunieme sa do dizajnéra hlavného formulára, kde si pridáme metódu k
udalosti Click ovládacieho prvku addButton. V kóde
hlavného formulára si dopíšeme telo vygenerovanej obslužnej metódy prvku
addButton:
private void addButton_Click(object sender, EventArgs e) { User user = new User { FirstName = firstNameTextBox.Text, LastName = lastNameTextBox.Text, BirthDate = birthDateDateTimePicker.Value }; users.Add(user); usersListBox.DataSource = null; usersListBox.DataSource = users; }
Najprv vytvoríme nového používateľa s dátami z našich kontroliek.
Potom ho pridávame do našej kolekcie users. Nakoniec ešte
musíme obnoviť zdroj dát nášho používateľa v prvku
usersListBox. Na to nám poslúži vlastnosť
DataSource.
Testovanie
Spustite si aplikáciu. Skúsme si pridať len jedného používateľa, aby sme si boli istí, že nám aplikácia funguje.
Serializácia dát
Teraz konečne môžeme prejsť na serializáciu dát. V kóde hlavného
formulára si napíšeme metódu Serialize():
private void Serialize() { try { XmlSerializer serializer = new XmlSerializer(users.GetType()); using (StreamWriter sw = new StreamWriter("users.xml")) { serializer.Serialize(sw, users); } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
V bloku try vytvoríme inštanciu serializer typu
XmlSerializer na kolekcii typu List<User>. Potom
vytvoríme stream sw typu StreamWriter, pomocou
ktorého budeme serializovať. Potom voláme metódu Serialize(),
ktorej:
- v prvom parametri odovzdáme náš stream
sw, - v druhom parametri odovzdáme našu kolekciu
users, ktorej dáta chceme serializovať.
V bloku catch vypíšeme prípadnú vzniknutú výnimku.
Teraz sa vrátime späť do designera. Pri formulári nájdeme
Event (udalosť) OnClosing, na ktorú dvakrát
klikneme. Vo vygenerovanej metóde v kóde hlavného formulára zavoláme našu
metódu Serialize():
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { Serialize(); }
Testovanie
Spustíme aplikáciu, pridáme nejakých používateľov a potom aplikáciu
zatvoríme. Kolekcia používateľov sa serializuje a uloží do priečinka s
aplikáciou na ceste .../bin/Debug/users.xml. Keď súbor
otvoríme, uvidíme zapísané dáta:
<?xml version="1.0" encoding="utf-8"?> <ArrayOfUser xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <User> <FirstName>John</FirstName> <LastName>Smith</LastName> <BirthDate>2014-09-05T23:09:19</BirthDate> </User> <User> <FirstName>James</FirstName> <LastName>Brown</LastName> <BirthDate>2014-09-05T23:09:19</BirthDate> </User> </ArrayOfUser>
Deserializácie
Serializáciu máme, tak teraz ešte deserializáciu. Z pohľadu na kód je
to trošku ťažšie a preto si radšej všetko vysvetlíme ešte raz. Najprv si
do kódu hlavného formulára napíšeme metódu Deserialize():
private void Deserialize() { try { if (File.Exists("users.xml")) { XmlSerializer serializer = new XmlSerializer(users.GetType()); using (StreamReader sr = new StreamReader("users.xml")) { users = (List<User>)serializer.Deserialize(sr); } } else throw new FileNotFoundException("File not found"); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
Najprv musíme zistiť, či vôbec daný XML súbor s dátami existuje. Na to
nám poslúži trieda File a jej metóda
Exists(string path), ktorá vracia hodnotu typu bool.
V tele podmienky vytvoríme serializer typu
XmlSerializer na typ List našej kolekcie
používateľov.
Ďalej vytvoríme StreamReader s cestou k nášmu súboru. Potom
zavoláme metódu Deserialize() z triedy
XmlSerializer. Je tu ale drobný detail, a to že metóda
Deserialize() vracia object. Musíme tu teda
pretypovať na List<User>, než priradíme
uložených používateľov k našim existujúcim.
Teraz prejdeme do dizajnéra hlavného formulára. Vo vlastnostiach
(properties) formulára nájdeme udalosť Load, ku ktorej si
necháme vygenerovať obslužnú metódu, ktorej telo vyplníme takto:
private void Form1_Load(object sender, EventArgs e) { Deserialize(); usersListBox.DataSource = users; }
V tele metódy zavoláme našu metódu Deserialize(). Potom
ešte načítame našich používateľov do nášho prvku
ListBox.
Testovanie
Spustíme aplikáciu, naplníme kolekciu dátami a aplikáciu zatvoríme. Potom ju znovu otvoríme a uvidíme, že obsahuje všetkých používateľov, ktorých sme tam pridali:

Záver
Trieda, ktorú serializujeme, musí obsahovať bezparametrický konštruktor, alebo žiadny parametrický. Je to z toho dôvodu, že deserializér si najskôr vytvorí prázdnu inštanciu a potom postupne zadáva vlastnosti, ako ich číta zo súboru alebo iného streamu. Nemôžeme serializovať ovládacie prvky, či už defaultné alebo nami vytvorené (User Control).
V nasledujúcom cvičení, Riešené úlohy k 6.-10. lekcii práce so súbormi v C# .NET, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 7x (87.46 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#
