Serializace
Serializace je ve stručnosti řečeno konverze objektu na lineární sekvenci bytů a deserializace je proces opačný. S trochou fantazie serializace a deserializace funguje jako "Teleport" :-) Samotné windows využívají serializace pro mnoho důležitých úkolů, jako jsou např. webové služby, remoting či kopírování položek do schránky.
Serializace Objektu
Postup při serializaci:
- Vytvoření streamu ve kterém budeme chtít uchovávat serializovaná data
- Vytvoření isntance třídy BinaryFormatter
- Zavolání metody Serialize, kde prvním parametrem bude stream a druhým objekt
// pridame referenci System.Runtime.Serialization
// a nesmime zapomenout na tyhle namespace
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
class Program
{
static void Main(string[] args)
{
// vytvorim si objekt, v mem pripade string,
// ktery budu chtit serializovat
string str = "toto je test serializace";
// Vytvorim si stream, ve kterem budu uchovavat
// serializovany objekt
using (FileStream fs =
new FileStream("serializace.data", FileMode.OpenOrCreate))
{
// Vytvorim si instanci tridy BinaryFormatter
BinaryFormatter binaryFormatter = new BinaryFormatter();
// serializuju objekt
binaryFormatter.Serialize(fs, str);
}
}
}
|
Serializovaný text vypadá takhle (Uvnitř souboru se nachází náš text a před ním i za ním je sekvence bytů sloužící pro deserializaci). Pokud bych si chtěl uložit string tak stačí když si ho pouze zapíšu do souboru a nemmusím využívat serializace, proto berte tuhle ukázku jenom jako informativní způsob jak serializovat data

Deserializace Objektu
Postup při deserializaci:
- Otevření streamu, který obsahuje serializovaná data
- Vytvoření instance třídy BinaryFormatter
- Vytvoření nového objektu, který bude uchovávat deserializovaná data
- zavolání metody Deserialize, kde parametrem bude stream a přetypováním na správný typ
static void Main(string[] args)
{
// vytvorim si objekt ve kterem budu
// uchovavat deserializovana data
string novyStr = string.Empty;
// Vytvorim si stream, ze ktereho budu cist data
using (FileStream fs =
new FileStream("serializace.data", FileMode.Open))
{
// Vytvorim si instanci tridy BinaryFormatter
BinaryFormatter binaryFormatter = new BinaryFormatter();
// deserializuju objekt
novyStr = (string)binaryFormatter.Deserialize(fs);
// vypisu obsah promenne novyStr
Console.WriteLine(novyStr); // toto je test serializace
}
}
|
Nyní se podíváme na způsob jak serializovat celé třídy. Představte si, že máme třídu, která obsahuje vlastnosti jméno a vek. Aby šla třída serializovat musíme jí označit atributem [Serializable].
[Serializable]
class Test
{
private string m_Jmeno;
private int m_Vek;
private int m_RokNarozeni;
public Test(string jmeno, int rokNarozeni)
{
m_Jmeno = jmeno;
m_RokNarozeni = rokNarozeni;
m_Vek = DateTime.Now.Year - rokNarozeni;
}
public string Jmeno
{
get { return m_Jmeno; }
set { m_Jmeno = value; }
}
public int Vek
{
get { return m_Vek; }
set { m_Vek = value; }
}}
|
Vytořím tedy novou instanci a serializuju
static void Main(string[] args)
{
Test t = new Test("ja", 1987);
using (FileStream fs = new FileStream("Test.data", FileMode.OpenOrCreate))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, t);
}
}
|
Nyní soubor odešlu kamarádovi, který je bohužel zaneprázdněn a daný soubor deserializuje až po několika letech. Ovšem ve vlastnosti vek bude stale věk zadaný mnou. jak to tedy vyřešit ? Řešení je implementovat rozhraní IDeserializationCallback, které obsahuje metodu OnDeserialization. Tato metoda se provede při vykonávání deserializace a můžeme tedy ošetřit aby byl zadaný věk přepočítán
[Serializable]
class Test : IDeserializationCallback
{
private string m_Jmeno;
// vek tedy neni nutno serializovat,
// bude prepocitan behem deserializace
[NonSerialized]
private int m_Vek;
private int m_RokNarozeni;
public Test(string jmeno, int rokNarozeni)
{
m_Jmeno = jmeno;
m_RokNarozeni = rokNarozeni;
m_Vek = DateTime.Now.Year - rokNarozeni;
}
public string Jmeno
{
get { return m_Jmeno; }
set { m_Jmeno = value; }
}
public int Vek
{
get { return m_Vek; }
set { m_Vek = value; }
}
#region IDeserializationCallback Members
public void OnDeserialization(object sender)
{
m_Vek = DateTime.Now.Year - m_RokNarozeni;
}
#endregion
}
|
K serializaci můžeme využít místo BinaryFormatter tzv. SoapFormater. Jedná se o XML formát, tedy platformě nezávislý. Já se zde o SoapFormatteru moc zminovat nebudu a spíše se rovnou vrhnu na XML serializaci.