Курс лекций для студентов специальности i-31 03 04 Информатика всех форм обучения Минск 2010



страница17/29
Дата09.08.2019
Размер0.64 Mb.
#126834
ТипКурс лекций
1   ...   13   14   15   16   17   18   19   20   ...   29

2.20. СЕРИАЛИЗАЦИЯ


Сериализация  это процесс, при котором данные объекта переносятся из памяти в поток данных для сохранения. Десериализация – обратный процесс, заключающийся в восстановлении состояния объекта из потока. При выполнении сериализации следует учитывать несколько нетривиальных моментов. Например, сохранение полей объекта требует сохранения всех данных агрегируемых объектов – то есть требуется сохранить граф зависимых объектов.

Платформа .NET предлагает три основных механизма сериализации:

1. Сериализация времени выполнения.

2. Сериализация контрактов данных.

3. XML-сериализация.

При рассмотрении примеров сериализации будем использовать классы, описывающие одного студента и группу студентов.

public class Student : IComparable

{

public string Name { get; set; }



public int Age { get; set; }

public double GPA { get; set; } // Grade Point Average, средний балл


public int CompareTo(Student other)

{

return GPA.CompareTo(other.GPA);



}

}
public class Group : Collection

{

public Student BestStudent; // поле, а не свойство



public double GPA { get; private set; }
public double CalculateGPA()

{

return GPA = Items.Select(student => student.GPA).Average();



}
public Student FindTheBest()

{

return BestStudent = Items.Max();



}

}
// пример использования классов Student и Group

var group = new Group {

new Student {Name = "Smirnov", Age = 18, GPA = 9},

new Student {Name = "Ivanova", Age = 20, GPA = 6.67},

new Student {Name = "Kuznetsov", Age = 18, GPA = 6},

new Student {Name = "Sokolov", Age = 20, GPA = 7.67},

new Student {Name = "Lebedeva", Age = 20, GPA = 9}};


Сериализация времени выполнения


Основные классы, связанные с сериализацией времени выполнения (runtime serialization), размещены в пространствах имён с префиксом System.Runtime.Serialization. Например, сериализацию в двоичном формате обеспечивают классы из System.Runtime.Serialization.Formatters.Binary.

Сериализация времени выполнения применима только к объектам сериализуемых типов. Сериализуемый тип – это тип, помеченный атрибутом [Serializable]1, у которого все поля имеют сериализумый тип. Все базовые типы платформы .NET являются сериализуемыми. Если планируется сериализация объекта group, необходимо добавить атрибут [Serializable] к классам Group и Student. Сериализация некоторых полей может не иметь смысла (например, эти поля вычисляются при работе с объектом или хранят конфиденциальные данные). Для таких полей можно применить атрибут [NonSerialized].

Изменим код классов Group и Student с учетом вышесказанного:

[Serializable]

public class Student : IComparable

{

// элементы класса не показаны



}
[Serializable]

public class Group : Collection

{

[NonSerialized] // атрибут применяется к полю, а не к свойству



public Student BestStudent;
// неизменившиеся элементы класса не показаны

}

Сериализуемые типы можно сохранить в поток в различных форматах. Платформа .NET имеет классы, поддерживающие двоичный формат и формата SOAP1. При необходимости разработчик может создать класс для поддержки собственного формата сериализации.



Осуществим сериализацию объекта group в двоичном формате. Используем для этого экземплярный метод Serialize() класса BinaryFormatter. Метод принимает два аргумента: поток сериализации и сериализуемый объект:

var formatter = new BinaryFormatter();

using (Stream s = File.Create("group.dat"))

{

formatter.Serialize(s, group);



}

Метод Deserialize() класса BinaryFormatter выполняет десериализацию:

using (Stream s = File.OpenRead("group.dat"))

{

group = (Group)formatter.Deserialize(s);



}

Метод десериализации размещает объект в памяти и возвращает ссылку на него. При этом конструкторы типа не вызываются. Это может стать проблемой, если нужна особая инициализация объекта и восстановление [NonSerialized]-полей. Тип может реализовать интерфейс IDeserializationCallback, который содержит единственный метод OnDeserialization(), вызываемый автоматически после десериализации объекта.

[Serializable]

public class Group : Collection, IDeserializationCallback

{

// после десериализации заполним поле BestStudent



// CLR не поддерживает работу с параметром sender

void OnDeserialization(object sender)

{

FindTheBest();



}
// неизменившиеся элементы класса не показаны

}

Альтернативой IDeserializationCallback являются атрибуты [OnSerializing], [OnSerialized], [OnDeserializing], [OnDeserialized], применимые к методам. Помеченные методы вызываются автоматически до и после сериализации или десериализации соответственно. Метод, который помечен одним из указанных атрибутов, должен принимать в качестве аргумента объект класса StreamingContext1 и не возвращать значений. Каждый из атрибутов может применяться только к одному методу в типе.



[Serializable]

public class Group : Collection

{

[OnDeserialized]



private void AfterDeserialization(StreamingContext context)

{

FindTheBest();



}
// неизменившиеся элементы класса не показаны

}

Атрибут [OptionalField] применяется к полю и подавляет при десериализации генерацию исключения, если помеченное поле не найдено в потоке данных. Это позволяет сохранять «старые» объекты, затем модифицировать тип, расширяя состав его полей, и десериализовать данные в «новые» объекты типа.



Если программиста не устраивает способ организации потока сериализуемых данных, он может повлиять на этот процесс, реализуя в сериализуемом типе интерфейс ISerializable:

public interface ISerializable

{

void GetObjectData(SerializationInfo info,



StreamingContext context);

}

Интерфейс позволяет выполнить любые действия, связанные с формированием данных для сохранения. Метод GetObjectData() вызывается CLR автоматически при выполнении сериализации. Реализация метода подразумевает заполнение объекта SerializationInfo набором данных вида «ключ-значение», которые (обычно) соответствуют полям сохраняемого объекта. Класс SerializationInfo содержит перегруженный метод AddValue(), набор методов вида GetПримитивныйТип(), а также свойства для указания имени типа и сборки сериализуемого объекта. Если тип реализует интерфейс ISerializable, он должен содержать специальный private-конструктор, который будет вызывать CLR после выполнения десериализации. Конструктор должен иметь параметр типа SerializationInfo и параметр типа StreamingContext.



Рассмотрим пример реализации ISerializable в классе Student.

[Serializable]

public class Student : IComparable, ISerializable

{

// не показаны свойства и метод CompareTo()



// неявная реализация интерфейса ISerializable

void ISerializable.GetObjectData(SerializationInfo info,

StreamingContext ctx)

{

info.SetType(typeof(Student));



info.AddValue("Name", Name);

info.AddValue("Age", Age);

info.AddValue("Mark", (int)(GPA * 10));

}
private Student(SerializationInfo info, StreamingContext ctx)

{

Name = info.GetString("Name");



Age = info.GetInt32("Age");

GPA = info.GetInt32("Mark") / 10.0;

}
public Student() { }

}


Каталог: images
images -> В списке студентов (или магистрантов)
images -> Н. И. Сулейманов Комплект контрольно-оценочных средств для оценки результатов освоения профессионального модуля разработан на основе Федерального государственного образовательного стандарта среднего профессионального
images -> По направлению подготовки
images -> Добавить гаджеты. Добавление гаджетов
images -> Техническое задание № apnip/C. 2/CS/Ind/01 Международный консультант по улучшенной производительности орошаемого земледелия
images -> Комплект контрольно-оценочных средств по профессиональному модулю пм. 01 Техническое обслуживание и ремонт автотранспорта


Поделитесь с Вашими друзьями:
1   ...   13   14   15   16   17   18   19   20   ...   29




База данных защищена авторским правом ©vossta.ru 2022
обратиться к администрации

    Главная страница