Lekce 10 - Serializace a deserializace v C# .NET
V minulé lekci, LINQ to XML v C# .NET, jsme si představili technologii LINQ to XML.
V dnešním C# .NET tutoriálu si řekneme něco o serializaci a deserializaci.
Serializace je uchování stavu objektu. Trochu odborněji by se to dalo popsat jako konvertování objektu na proud bytů a poté uložení někde do paměti, databáze nebo souboru. Deserializace je opak serializace. Dalo by se říci, že tedy převedete zpátky proud bytů na kopii objektu.
K čemu je to dobré?
Serializace vám umožní uložit stav objektu a potom pomocí deserializace si ho kdykoliv znovu vytvořit. Pomocí serializace se třeba posílají data skrz síť nebo se ukládá nastavení aplikace.
Ukázková aplikace
Založíme si nový projekt typu Windows Forms Application.
Poté si vytvoříme nějakou třídu, její instanci bychom chtěli zachovat a
při opětovném spuštění aplikace ji mít ve stavu, v jakém jsme ji při
zavření aplikace zanechali. Třídu nazveme Uzivatel
a dáme jí
vlastnosti Jmeno
, Prijmeni
a
DatumNarozeni
. Třída by teda mohla vypadat nějak takto
(všimněte si, že je veřejná):
public class Uzivatel { public string Jmeno { get; set; } public string Prijmeni { get; set; } public DateTime DatumNarozeni { get; set; } }
Na hlavní formulář si přidáme tedy dva TextBox
y na jméno a
příjmení. Ještě si přidáme ovládací prvek DateTimePicker
,
abychom mohli určit datum uživatele. Dále si někde umístíme tlačítko,
kterým budeme přidávat uživatele do naší aplikace. Přidáme prvek
ListBox
pro zobrazení uživatelů. Nakonec si přejmenujeme naše
ovládací prvky ze základního jména na nějaké, abychom se v nich vyznali.
Viz. obrázek.
Dále si vytvoříme kolekci typu List<Uzivatel>
, abychom
měli uživatele kde v aplikaci uchovávat. Přesuneme se tedy do kódu
hlavního formuláře (Form1
nebo u mě FormMain
) a
dopíšeme si do třídy tuto privátní kolekci.
private List<Uzivatel> uzivatele = new List<Uzivatel>();
Přesuneme se zpátky do designeru formuláře a přidáme si metodu k
události Click
u ovládacího prvku btnPridej
.
Dopíšeme zde kód, který přidá uživatele do naší kolekce. Dále ještě
musíme ukázat uživatele v listBoxUzivatele
. K tomu nám
poslouží vlastnost DataSource
.
private void btnPridej_Click(object sender, EventArgs e) { // Vytvoříme nového uživatele s daty z našich kontrolek Uzivatel uzivatel = new Uzivatel { Jmeno = tbJmeno.Text, Prijmeni = tbPrijmeni.Text, DatumNarozeni = dateTimePicker.Value }; // Přidáme ho do naší kolekce uzivatele.Add(uzivatel); // Obnovíme zdroj dat našeho listBoxUzivatele listBoxUzivatele.DataSource = null; listBoxUzivatele.DataSource = uzivatele; }
Teď již máme vcelku funkční aplikaci. Když aplikaci spustíte a
zkusíte uživatele přidat, uvidíte, že se přidala vlastně jen položka
"NazevProjektu.Uzivatel"
. Přesuneme se tedy do souboru
Uzivatel
a přepíšeme metodu ToString()
. Třeba
nějak takto:
public override string ToString() { return "Jméno: " + Jmeno + " Přijmení: " + Prijmeni + " Datum Narození: " + DatumNarozeni.ToShortDateString(); }
Zkuste si přidat uživatele teď a vidíme, že se uživatel zobrazuje lidštěji.
Serializace
Nyní konečně můžeme přejít k serializaci dat. Vytvoříme si tedy
metodu Serializuj()
v kódu formuláře.
private void Serializuj() { try { // Vytvoříme si XmlSerializer na typ List<Uzivatel> XmlSerializer serializer = new XmlSerializer(uzivatele.GetType()); // Alternativní forma, jak by to šlo také zapsat //XmlSerializer serializer = new XmlSerializer(typeof(List<Uzivatel>)); // Vytvoříme Stream pomocí kterého budeme serializovat using (StreamWriter sw = new StreamWriter("uzivatele.xml")) { // Zavoláme metodu Serialize(), kde první parametr je Stream // Ten jsme vytvořili o řádek výše // Druhý parametr je objekt, který serializujeme serializer.Serialize(sw, uzivatele); } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
Využili jsme serializer do formátu XML. Serializerů je několik typů
včetně binárního, poskytuje nám je již připravené .NET framework.
Nemusíme se tedy starat o nic, instance se serializují automaticky. Nyní se
vrátíme zpátky do designeru a u formuláře najdeme Event (událost)
OnClosing
, 2x klikneme a v obslužném kódu zavoláme naší
metodu Serializuj()
.
private void FormMain_FormClosing(object sender, FormClosingEventArgs e) { Serializuj(); }
Pozn. Název metody se může lišit podle názvu hlavního formuláře.
Jestli jste jeho jméno neupravovali, budete mít na začátku nejspíš prefix
Form1
.
Když nyní spustíme program, přidáme nějaké uživatele a program
zavřeme, kolekce uživatelů se serializuje a uloží do
NazevProjektu/Bin/Debug/uzivatele.xml
. Když soubor otevřeme, měl
by být čitelný. U mě soubor vypadá nějak takto:
<?xml version="1.0" encoding="utf-8"?> <ArrayOfUzivatel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Uzivatel> <Jmeno>Jan</Jmeno> <Prijmeni>Novák</Prijmeni> <DatumNarozeni>2013-07-11T17:27:19</DatumNarozeni> </Uzivatel> <Uzivatel> <Jmeno>Jakub</Jmeno> <Prijmeni>Špatný</Prijmeni> <DatumNarozeni>2013-07-11T17:27:19</DatumNarozeni> </Uzivatel> </ArrayOfUzivatel>
Deserializace
Serializaci máme, tak teď ještě deserializaci. Z pohledu na kód je to
trošku těžší, proto raději všechno vysvětlím ještě jednou.
Vytvoříme metodu Deserializuj()
v kódu hlavního formuláře.
Nejprve musíme zjistit, jestli vůbec daný XML soubor s daty existuje. K tomu
nám poslouží třída File
a metoda
Exists(string path)
, která vrací bool
. Do těla
podmínky už vytvoříme XmlSerializer
na typ našeho
List
u uživatelů. Dále vytvoříme StreamReader
s
cestou k našemu souboru a pak jen zavoláme metodu Deserialize()
z
třídy XmlSerializer
. Je tu ale drobný detail, a to že metoda
Deserialize()
vrací object
. Musíme zde tedy
přetypovat, než přiřadíme uložené uživatele k našim
stávajícím. Celá metoda tedy vypadá ve finále takto:
private void Deserializuj() { try { if (File.Exists("uzivatele.xml")) { XmlSerializer serializer = new XmlSerializer(uzivatele.GetType()); using (StreamReader sr = new StreamReader("uzivatele.xml")) { uzivatele = (List<Uzivatel>)serializer.Deserialize(sr); } } else throw new FileNotFoundException("Soubor nebyl nalezen"); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
Tuto metodu zavoláme v události formuláře Load
. Přejdeme
tedy do designeru a ve vlastnostech (properties) formuláře najdeme událost
Load
a vytvoříme její obslužnou metodu. V ní zavoláme naší
metodu Deserializuj()
a k tomu ještě potřebujeme načíst naše
uživatele do našeho ListBox
u. Celá metoda vypadá tedy
takto:
private void FormMain_Load(object sender, EventArgs e) { Deserializuj(); listBoxUzivatele.DataSource = uzivatele; }
Pozn. Název metody se může lišit podle názvu hlavního formuláře.
Jestli jste jeho jméno neupravovali, budete mít na začátku nejspíše prefix
Form1
.
Když aplikaci spustíte a naplníte daty, zavřete a znovu otevřete, měla by obsahovat všechny uživatele, které jste tam přidali.
Závěr
Na závěr bych chtěl říct pár věcí, na které nejspíš přijdete i sami, když budete serializovat objekty vaší aplikace.
- Třída, kterou serializujete, musí obsahovat bezparametrický konstruktor (nebo žádný parametrický). Je to z toho důvodu, že deserializer si nejdříve vytvoří prázdnou instanci a potom postupně zadává vlastnosti jak je čte ze souboru (nebo jiného streamu).
- Nemůžete serializovat ovládací prvky, ať již defaultní a nebo vámi vytvořenou (User Control). Kdybyste ale chtěli, určitě nepotřebujete serializovat úplně všechno, takže si můžete uložit jen ty věci, které opravdu potřebujete.
- K serializaci patří několik atributů, jako:
[XmlIgnore]
- Nebude vám danou propertu serializovat.[Serializable()]
- Dává se nad deklaraci třídy, dáváte tomu jasně najevo, že se bude objekt serializovat.(Implementuje interfaceISerializable
)[XmlAttribute("Name")]
změní XML element z párového na nepárový a hodnota dané property bude v atributuName
. Například<Uzivatel Name="Jan">
místo<Jmeno>Jan</Jmeno>
.
- Kdyby jste někdy chtěli serializovat třídu
Color
, tak ona se sice serializuje, ale v souboru nemá žádnou hodnotu, proto můžete např. serializovatColor
jako hexadecimální číslo a při deserializaci si ho jednoduše překonvertujete na barvu.
V následujícím cvičení, Řešené úlohy k 6.-10. lekci práce se soubory v C# .NET, si procvičíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 577x (58.1 kB)
Aplikace je včetně zdrojových kódů v jazyce C#