10. diel - Serializácia a deserializácia v C# .NET
V minulej 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 C# .NET tutoriále 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 teda 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. Založme 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">
miesto
<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
TextBox
s názvomfirstNameTextBox
alastNameTextBox
na meno a priezvisko. - Prvok
DateTimePicker
s názvombirthDateDateTimePicker
pre dátum narodenia. - Tlačidlo s názvom
addButton
pre pridanie užívateľa do našej aplikácie. - Prvok
ListBox
s názvomusersListBox
pre zobrazenie uží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 užívateľa v prvku
usersListBox
. K tomu 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()
,
ktoré:
- 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
Spustite aplikáciu, pridajme nejakých uží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. K
tomu 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 uží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 nasledovne:
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 uží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 uží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 deserializer 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é 0x (86.98 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#