Poznáváme C# a Microsoft.NET 40. díl – serializace

Dnešní díl se začneme věnovat serializaci. Vysvětlíme si co tento pojem znamená, jak vytvářet serializovatelné typy a jakými způsoby tyto typy serializovat.

Co je to serializace?

Mnoho instancí, které při svém programování používáme mají celkem krátký „život“. Jsou nějakou cestou (konstruktorem, skrze reflexi, tovární metodou…) vytvořeny, po té jsou nějakým způsobem použity a pak když nejsou potřeba (neexistuje na ně jakákoliv reference)  jsou při úklidu (Garbage collection) Garbage collectorem odstraněny z paměti. Ovšem, ne všechny instance jsou používány takto krátce a některé instance nesoucí potřebná data potřebujeme zachovat na delší dobu. To dokážeme zařídit tak, že onu instanci uložíme do nějakého perzistentního úložiště (relační databáze, soubor..). Takovémuto uložení instance do perzistentního úložiště se říká Serializace.  V podstatě jde o to, že instance je převedena na Stream, tím pádem může být, jak již bylo řečeno, uložena, ale také díky tomu, že je Streamem, i poslána např. pomocí HTTP protokolu na zcela jiný počítač. Serializovatelné typy, musí být i ty, které jsou používány při takzvaném remotingu, což je možnost používat objekty mezi různými aplikačními doménami. Opačnému procesu, tedy procesu pří kterém je z nějakého proudu vytvořena instance, se naopak říká Deserializace.

Jak učinit typy serializovatelnými?

K tomu, abychom naše typy učinili serializovatelnými (schopnými se serializovat) vedou dvě cesty. První cestou je použití atributu System.Serializable, což je cesta jednodušší a v obvyklých aplikacích častěji používaná. Druhým způsobem je nechat námi vytvářený typ implementovat rozhraní System.ISerializable. My se dnes budeme zabývat použitím atributu Serializable. V případě použití tohoto atributu na náš typ se o průběh serializace instance tohoto typu kompletně postará běhové prostředí .NET runtime. Takže pokud bychom chtěli mít třídu představující osobu a chtěli bychom, aby bylo možné instance této třídy serializovat, provedeme to jednoduše takto :

/// <summary>
/// Ukazkova trida predstavujici osobu, jejiz instance mohou byt serializovany
/// </summary>
[Serializable]
public class Osoba
{
 private DateTime datumNarozeni;
 private string jmeno;
 private string prijmeni;

 public Osoba(string Jmeno, string Prijmeni, DateTime DatumNarozeni)
 {
  this.jmeno = Jmeno;
  this.prijmeni = Prijmeni;
  this.datumNarozeni = DatumNarozeni;
 }

 //zbytek tridy
}

V případě této výchozí serializace ( = použití atributu Serializable) jsou serializovány všechny datové členy daného typu a to včetně těch soukromých. Je důležité vědět, že všechny typy, kterých jsou datové členy daného typu musí být taktéž serializovatelné. Pokud by tomu tak nebylo a pokusili bychom se o serializaci, došlo by k vyhození výjimky System.Runtime.Serialization.SerializationException.

/// <summary>
/// Tato trida by nemohla byt serialozovana protoze obahuje datovy clen
/// ktery nelze serializovat
/// </summary>
[Serializable]
public class NemoznaSerializace
{
 NeserializovatelnyTyp clen;
}

public struct NeserializovatelnyTyp
{
 //implementace typu
}

I když je třída označena atributem Serializable, její datový člen není a proto ji nelze serializovat. V případě naší ukázkové třídy Osoba, není se serializací problém, protože všechny typy datových členů (String a DateTime), jejichž definici obsahuje, jsou označeny jako serializovatelné.

Jak instanci serializovat?

Nyní když víme jakým způsobem učinit typ serializovatelným a také jaké je potřeba dodržet pravidla, potřebujeme ještě vědět jak vlastní serializaci provedeme. Ve jmenném prostoru System.Runtime.Serialization se nachází rozhraní IFormatter, které předepisuje funkcionalitu pro formátování serializovaných objektů. Přesněji, obsahuje předpis pro metody Serialize a Deserialize, které zařizují, jak název napovídá, vlastní serializaci respektive deserializaci. V základní knihovně tříd .NET frameworku jsou pro naše použití k dispozici dvě základní implementace tohoto rozhraní a to třídy BinaryFormatter a SoapFormatter.

 

Klepněte pro větší obrázek

 

BinaryFormatter je implementace, která serializuje a desearilizuje objekty v binárním formátu a nalezneme ji ve jmenném prostoru System.Runtime.Serialization.Formatters.Binary. SoapFormatter zase serializuje a deserializuje objekty do formátu SOAP, což je v podstatě implementace XML a nachází se ve jmenném prostoru System.Runtime.Serialization.Formatters.Soap. Následující příklad demostruje použití serializace instance třídy Osoba do binárního formátu, tedy pomocí třídy BinaryFormatter.

public static void Serializace()
{
 DateTime lDate = new DateTime(1984,2,9);
 Osoba lOsoba = new Osoba("Jan","Novak",lDate);
Stream lStream = new FileStream("C:/test.bin",FileMode.Create);
 IFormatter lFormatter = new BinaryFormatter();
 try
 {
  lFormatter.Serialize(lStream,lOsoba);
 }
 finally
 {
  lStream.Close();
 }

}

Metodě Serialize předáme ve formě parametrů referenci na Stream, který vede ke konkrétnímu úložišti a samotnou instanci, kterou chceme serializovat. V našem případě jsme nechali instanci serializovat do souboru. A jak instanci deseralizujeme? To už ukazuje tento příklad :

public static void Deserializace()
{
 IFormatter lFormatter = new BinaryFormatter();
 Stream lStream = new FileStream("C:/test.bin",FileMode.Open);
 Osoba lOsoba = null;
 try
 {
  lOsoba = (Osoba) lFormatter.Deserialize(lStream);
  Console.WriteLine("Deserializovana osoba je {0} {1}",lOsoba.Jmeno,lOsoba.Prijmeni);
 }
 finally
 {
  lStream.Close();
 }
}

Deserializace instance je také velmi jednoduchá záležitost. Jediné co metodě Deserialize musíme předat je odkaz na Stream vedoucí k úložišti instance.

Pokud bychom chtěli instanci serializovat do formátu SOAP, jediné co bude ve zdrojovém kódu jiné bude záměna použité instance třídy BinaryFormatter za instanci třídy SoapFormatter. Obecně platí, že pro serializaci do souboru je vhodnější použít binární formát, protože výsledný soubor je o dost menší a mimo to také výrazně rychlejší.

Příští díl bude opět pojednávat o serializaci. Dozvíme se jak mít serializaci více pod kontrolou a zjistíme, že není nutné serializovat všechny datové členy instance typu.

Zdrojové kódy k příkladům naleznete zde.

Diskuze (2) Další článek: Chystá se senzační akvizice: hodlá eBay spolknout Skype Technologies?

Témata článku: Software, Microsoft, Programování, Krátký život, Stream, Díl, Jediný způsob, Public, Private, Jediná cesta, Garbage, Reference, Soap


Určitě si přečtěte

Severní magnetický pól „odcestoval“ z Kanady na Sibiř. Vědci musí upravit model

Severní magnetický pól „odcestoval“ z Kanady na Sibiř. Vědci musí upravit model

** Zemské magnetické pole se chová nepředvídatelně ** Severní magnetický pól se posouvá z Kanady směrem na Sibiř ** Vědci musí rychle aktualizovat Světový magnetický model

Karel Kilián | 30

Více systémů na jednom počítači: Vybrali jsme nejlepší programy pro virtualizaci

Více systémů na jednom počítači: Vybrali jsme nejlepší programy pro virtualizaci

** Chcete na svém počítači vyzkoušet jiný operační systém? ** Jednoduchá cesta vede přes virtualizaci ** Přinášíme pět nejlepších programů virtualizaci operačních systémů

Karel Kilián | 104

Nový iPhone a další novinky Applu: sledujte, na co se zase budou stát fronty

Nový iPhone a další novinky Applu: sledujte, na co se zase budou stát fronty

** Apple dnes představuje nové produkty v čele s novými iPhony ** Nemusí zůstat jen u telefonů, čekají se i další novinky ** Úvodní přednáška začíná v 19:00 našeho času

David Polesný | 57

Osudová havárie Concordu: Před 18 lety přišel konec nadzvukových dopravních letadel

Osudová havárie Concordu: Před 18 lety přišel konec nadzvukových dopravních letadel

** Concorde byl nejrychlejším dopravním letadlem ** Atlantik dokázal přeletět za cca 3 až 3,5 hodiny ** Před osmnácti lety tragická havárie provoz těchto letadel prakticky ukončila

David Polesný, Jiří Černý | 39