650 likes | 919 Views
Програмиране за .NET Framework. http:// www.nakov.com / dotnet-project /. Сериализация на данни. Михаил Стойнов Софтуерен инженер , Sciant Inc. www.sciant.com Microsoft Student Consultant www.fmi.uni-sofia.bg/microsoft/. Необходими знания.
E N D
Програмиране за .NET Framework http://www.nakov.com/dotnet-project/ Сериализация на данни Михаил Стойнов Софтуерен инженер, SciantInc.www.sciant.com Microsoft Student Consultant www.fmi.uni-sofia.bg/microsoft/
Необходими знания • Базови познания за .NET Framework и CLR (Common Language Runtime) • Базови познания за общата система от типове в .NET (Common Type System) • Базови познания за библиотеката от класове в .NET (Framework Class Library) • Познания за езика C# • Познания за потоци от данни • Базови познания за Reflection • Познания за Attributes • Познания заработа с XML в .NET Framework
Съдържание • Сериализация • XML сериализация • Приложение: FormatterServices
Сериализация • Сериализация • Какво e сериализация? • За какво се използва? • Защо сериализация? • Как се сериализира? • Видове форматeри (Formatters) • Процесът на сериализация • Малък пример – сериализация • Малък пример – десериализация • IDeserializationCallback • ISerializable • Контролиране на сериализацията • Streaming Contexts • XML Сериализация
Какво e сериализация? • Сериализация (Serialization) • Процес, който преобразува обект или свързан граф от обекти до поток от байтове • Потокът може да бъде двоичен (binary) или текстов (XML) • Десериализация (Deserialization) • Процес, който връща поток от байтове обратно до обекти • Напълно автоматизирани процеси • Предоставят, обаче, средства за фин контрол
За какво се използва? • Запазване на състоянието на обект • Една програма може да съхрани състоянието си на носител (файл, БД) • Предаване на обект през мрежа • Две програми могат да си предават данни • .NET Framework го използва вътрешно • за запазване на session state-а в ASP.NET • за копиране в clipboard от Windows Forms • за предаване на обекти по стойност от един Application Domain в друг • за дълбоко копиране (DeepCopy) • в Remoting технологията
За какво се използва? (2) • След като един обект бъде превърнат в поток от байтове, той може да бъде • криптиран • компресиран • Всички тези процеси са прозрачни • Не зависят от сериализирания обект • Могат да се сериализират циклични графи от обекти, т.е. обекти, които се реферират едни от други • Форматерът сериализира всеки обект само по веднъж – не влиза в безкраен цикъл
Защо сериализация? • Запазването на един обект може да се направи и ръчно, без сериализация • Представете си, обаче: • бизнес приложение с 10 000 класа • сложен граф от навързани обекти • код във всеки клас, който се справя с протоколи, несъвпадане на типовете при клиент/сървър, управление на грешки, обекти сочещи към други обекти, работа със структури, масиви, … • При по-старите платформи се работеше така • Сериализацията прави целия този процес прозрачен и автоматичен
Как се сериализира? String str = "Пие ми се бира!"; BinaryFormatter f = new BinaryFormatter(); using (Stream s = new FileStream("sample.bin")) { f.Serialize(s, str); } • Обектът, който ще се сериализира • Обектът може да бъде всякакъв тип – Int32, String, DateTime, Exception, Image, ArrayList, Hashtable, потребителски дефиниран клас, … • За него има специални изисквания (обяснени са по-късно)
Как се сериализира? String str = "Пие ми се бира!"; BinaryFormatter f = new BinaryFormatter(); using (Stream s = new FileStream("sample.bin")) { f.Serialize(s, str); } • Създаване на форматер (formatter) • Форматерът е специален клас, който имплементира IFormatter • Форматерът извършва цялата работа по сериализирането и десериализирането на йерархия (граф) от обекти
Как се сериализира? String str = "Пие ми се бира!"; BinaryFormatter f = new BinaryFormatter(); using (Stream s = new FileStream("sample.bin")) { f.Serialize(s, str); } • Потокът, в който ще се сериализират данните • Като параметър се очаква наследник на класа System.IO.Stream • Това означава, че обектът може да се сериализира вMemoryStream, FileStream, NetworkStream, …
Как се сериализира? String str = "Пие ми се бира!"; BinaryFormatter f = new BinaryFormatter(); using (Stream s = new FileStream("sample.bin")) { f.Serialize(s, str); } • Самият процес на сериализация • Форматерът обхожда (чрез reflection)всички член-променливи на обекта • Видимостта на член-променливата няма значение – сериализират се всички • Сериализират се само членове на инстанцията, без статичните членове
Видове форматери (Formatters) • Форматерите съдържат логиката за форматиране на сериализираните обекти • CLR обхожда метаданните за член-променливи и чрез reflection извлича стойностите им • Тези стойности се подават на форматера • Форматери (formatter) oт System.Runtime.Serialization • BinaryFormatter • SoapFormatter • потребителски дефинирани • Наследяват Formatter – абстрактен клас, даващ базова функционалност
Малък пример – сериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() { FirstExample obj = new FirstExample(); BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { f.Serialize(stream, obj); } } public void Deserialize() {...} }
Малък пример – сериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() { FirstExample obj = new FirstExample(); BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { f.Serialize(stream, obj); } } public void Deserialize() {...} }
Малък пример – сериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() { FirstExample obj = new FirstExample(); BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { f.Serialize(stream, obj); } } public void Deserialize() {...} }
Малък пример – сериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() { FirstExample obj = new FirstExample(); BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { f.Serialize(stream, obj); } } public void Deserialize() {...} }
Малък пример – сериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() { FirstExample obj = new FirstExample(); BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { f.Serialize(stream, obj); } } public void Deserialize() {...} }
Малък пример – сериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() { FirstExample obj = new FirstExample(); BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { f.Serialize(stream, obj); } } public void Deserialize() {...} }
Малък пример – сериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() { FirstExample obj = new FirstExample(); BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { f.Serialize(stream, obj); } } public void Deserialize() {...} }
Малък пример – сериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() { FirstExample obj = new FirstExample(); BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { f.Serialize(stream, obj); } } public void Deserialize() {...} }
Малък пример – сериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() { FirstExample obj = new FirstExample(); BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { f.Serialize(stream, obj); } } public void Deserialize() {...} }
Малък пример – десериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() {...} public void Deserialize() { BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { FirstExample fe = (FirstExample) • f.Deserialize(stream); } } }
Малък пример – десериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() {...} public void Deserialize() { BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { FirstExample fe = (FirstExample) • f.Deserialize(stream); } } }
Малък пример – десериализация using System.IO; using System.Runtime.Serialization.Formatters; [Serializable] class FirstExample { public int Number; [NonSerialized] public int Id; public string Name; } class Serializer { public void Serialize() {...} public void Deserialize() { BinaryFormatter f = new BinaryFormatter(); using (Stream stream = new FileStream("x.bin")) { FirstExample fe = (FirstExample) • f.Deserialize(stream); } } }
Демонстрация #1 • Бинарна сериализация
Демонстрация #2 • Сериализация по мрежата
Демонстрация #3 • Дълбоко копиране на обекти
IDeserializationCallback • Има случаи, в които се налага, след като обектът е десериализиран, да се направят някои допълнителни неща • Потребителят наследява IDeserializationCallback и имплементира метода OnDeserialization() • CLR изпълнява метода след пълната десериализация на обекта • Сигурно е, че в момента на изпълнение на метода всички член-променливи са вече десериализирани
Демонстрация #4 • IDeserializationCallback
ISerializable • Позволява предефиниране на автоматичната сериализация • .ctor(SerializationInfo info, StreamingContext context) • Не забравяйте :base(info, context) • ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) • Не забравяйте base.GetObjectData(info, context) • Забележка: Не забравяйте конструктора, защото компилаторът няма как да ви принуди да го напишете
Контролиране на сериализацията using System.Runtime.Serialization; [Serializable] class Person : ISerializable { private string mName; private int mAge; private Person(SerializationInfo aInfo, StreamingContext aContext) { mName = (string)аInfo.GetString("Person's name"); mAge = aInfo.GetInt32("Person's age"); } void ISerializable.GetObjectData(SerializationInfo aInfo, StreamingContext aContext) { aInfo.AddValue("Person's name", mName); aInfo.AddValue("Person's age", mAge); } }
Контролиране на сериализацията using System.Runtime.Serialization; [Serializable] class Person : ISerializable { private string mName; private int mAge; private Person(SerializationInfo aInfo, StreamingContext aContext) { mName = (string)aInfo.GetString("Person's name"); mAge = aInfo.GetInt32("Person's age"); } void ISerializable.GetObjectData(SerializationInfo aInfo, StreamingContext aContext) { aInfo.AddValue("Person's name", mName); aInfo.AddValue("Person's age", mAge); } }
Контролиране на сериализацията using System.Runtime.Serialization; [Serializable] class Person : ISerializable { private string mName; private int mAge; private Person(SerializationInfo aInfo, StreamingContext aContext) { mName = (string)аInfo.GetString("Person's name"); mAge = aInfo.GetInt32("Person's age"); } void ISerializable.GetObjectData(SerializationInfo aInfo, StreamingContext aContext) { aInfo.AddValue("Person's name", mName); aInfo.AddValue("Person's age", mAge); } }
Контролиране на сериализацията using System.Runtime.Serialization; [Serializable] class Person : ISerializable { private string mName; private int mAge; private Person(SerializationInfo aInfo, StreamingContext aContext) { mName = (string)аInfo.GetString("Person's name"); mAge = aInfo.GetInt32("Person's age"); } void ISerializable.GetObjectData(SerializationInfo aInfo, StreamingContext aContext) { aInfo.AddValue("Person's name", mName); aInfo.AddValue("Person's age", mAge); } }
Контролиране на сериализацията using System.Runtime.Serialization; [Serializable] class Person : ISerializable { private string mName; private int mAge; private Person(SerializationInfo aInfo, StreamingContext aContext) { mName = (string)аInfo.GetString("Person's name"); mAge = aInfo.GetInt32("Person's age"); } void ISerializable.GetObjectData(SerializationInfo aInfo, StreamingContext aContext) { aInfo.AddValue("Person's name", mName); aInfo.AddValue("Person's age", mAge); } }
Контролиране на сериализацията using System.Runtime.Serialization; [Serializable] class Person : ISerializable { private string mName; private int mAge; private Person(SerializationInfo aInfo, StreamingContext aContext) { mName = (string)аInfo.GetString("Person's name"); mAge = aInfo.GetInt32("Person's age"); } void ISerializable.GetObjectData(SerializationInfo aInfo, StreamingContext aContext) { aInfo.AddValue("Person's name", mName); aInfo.AddValue("Person's age", mAge); } }
Демонстрация #5 • Ръчна сериализация с ISerializable
Streaming Contexts • Указват къде се сериализира обектът • CrossProcess(0x0001), CrossMachines(0x0002), File(0x0004), Persistence(0x0008), Remoting(0x0010), Other(0x0020), Clone(0x0040), CrossAppDomain(0x0080), All(0x00FF) • Форматерът заявява за какво иска да сериализира, обектът решава как да реагира: • да сериализира различен брой параметри • да хвърли изключение, …
XML сериализация (съдържание) • Сериализация • XML сериализация • Какво е XML сериализация? • Контролиране на изходния XML • Контрол на сериализацията
Какво е XML сериализация? • Записването на публичните полета в XML формат с цел съхранение или транспорт • XML десериализация – обратният процес • XML сериализацията е част от поддръжката на XML в .NETFramework • Забележка: Сериализират се само публични членове! • XML сериализацията не може да се справи с циклично свързани графи от обекти • XML сериализацията може да сериализира всякакви обекти (няма изисквания) • Изисква се конструктор без параметри
XML сериализация – пример public class Student { public string Name; public int Age; public void SerializeToXml(Stream aStream) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(Student)); xmlSerializer.Serialize(aStream, this); } public static Student DeserializeFromXml( Stream aStream) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(Student)); return (Student) xmlSerializer.Deserialize(aStream); } }
Демонстрация #6 • Проста XML сериализация
Контролиране на изходния XML • Осъществява се с атрибути using System.Xml.Serialization; public class OptionalOrder { [XmlElement(ElementName = "Tax_Rate")] public decimal TaxRate; [XmlAttribute] public string FirstOrder; [XmlIgnoreAttribute] public bool FirstOrderSpecified; [XmlArrayAttribute("Items")] [XmlArrayItem("MemberName")] public OrderedItem[] OrderedItems; [XmlElement] public Employee[] Employees; }
Контролиране на изходния XML • Осъществява се с атрибути using System.Xml.Serialization; public class OptionalOrder { [XmlElement(ElementName = "Tax_Rate")] public decimal TaxRate; [XmlAttribute] public string FirstOrder; [XmlIgnoreAttribute] public bool FirstOrderSpecified; [XmlArrayAttribute("Items")] [XmlArrayItem("MemberName")] public OrderedItem[] OrderedItems; [XmlElement] public Employee[] Employees; }
Контролиране на изходния XML • Осъществява се с атрибути using System.Xml.Serialization; public class OptionalOrder { [XmlElement(ElementName = "Tax_Rate")] public decimal TaxRate; [XmlAttribute] public string FirstOrder; [XmlIgnoreAttribute] public bool FirstOrderSpecified; [XmlArrayAttribute("Items")] [XmlArrayItem("MemberName")] public OrderedItem[] OrderedItems; [XmlElement] public Employee[] Employees; }
Контролиране на изходния XML • Осъществява се с атрибути using System.Xml.Serialization; public class OptionalOrder { [XmlElement(ElementName = "Tax_Rate")] public decimal TaxRate; [XmlAttribute] public string FirstOrder; [XmlIgnoreAttribute] public bool FirstOrderSpecified; [XmlArrayAttribute("Items")] [XmlArrayItem("MemberName")] public OrderedItem[] OrderedItems; [XmlElement] public Employee[] Employees; }
Контролиране на изходния XML • Осъществява се с атрибути using System.Xml.Serialization; public class OptionalOrder { [XmlElement(ElementName = "Tax_Rate")] public decimal TaxRate; [XmlAttribute] public string FirstOrder; [XmlIgnoreAttribute] public bool FirstOrderSpecified; [XmlArrayAttribute("Items")] [XmlArrayItem("MemberName")] public OrderedItem[] OrderedItems; [XmlElement] public Employee[] Employees; }