Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






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






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

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

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

public class Student: IComparable< Student>

{

private string _name;

private double _gpa;

 

public string Name

{

get { return _name; }

set { _name = value; }

}

 

public double GPA // Grade Point Average, средний балл

{

get { return _gpa; }

set { _gpa = value; }

}

 

public int CompareTo(Student other)

{

return GPA.CompareTo(other.GPA);

}

}

 

public class Group: Collection< Student>

{

private Student _bestStudent;

private double _gpa;

 

public double GPA

{

get { return _gpa; }

}

 

public Student BestStudent

{

get { return _bestStudent; }

}

 

public double CalculateGroupGPA()

{

return _gpa = Items.Select(stud => stud.GPA).Average();

}

 

public Student FindTheBestStudent()

{

return _bestStudent = Items.Max();

}

}

 

// создадим объекты классов Student и Group

var group = new Group {

new Student {Name = " Smirnov", GPA = 9.1},

new Student {Name = " Ivanova", GPA = 6.7},

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

new Student {Name = " Sokolov", GPA = 7.6},

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

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

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

[Serializable]

public class Student: IComparable< Student>

{

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

}

 

[Serializable]

public class Group: Collection< Student>

{

// считаем, что поле _bestStudent является вычислимым

[NonSerialized]

private Student _bestStudent;

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

}

Объекты сериализуемых типов можно сохранить в поток в различных форматах. В частности, платформа.NET поддерживает двоичный формат при помощи класса BinaryFormatter. Его экземплярный метод Serialize() принимает два аргумента – поток сериализации и сериализуемый объект:

var formatter = new BinaryFormatter();

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

{

formatter.Serialize(s, group);

}

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

var formatter = new BinaryFormatter();

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

{

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

}

Метод Deserialize() размещает объект в памяти и возвращает ссылку на него. При этом конструкторы не вызываются. Это может стать проблемой, если нужна особая инициализация объекта и восстановление несохраненных полей. Платформа.NET содержит атрибуты [OnSerializing], [OnSerialized], [OnDeserializing], [OnDeserialized], применимые к методам сериализуемого типа. Помеченные методы вызываются CLR автоматически до и после сериализации или десериализации соответственно. Метод, который обозначен одним из указанных атрибутов, должен принимать в качестве аргумента объект класса StreamingContext[18] и не возвращать значений. Каждый из атрибутов может применяться только к одному методу в типе.

[Serializable]

public class Group: Collection< Student>

{

[OnSerializing]

private void BeforeSerialization(StreamingContext context)

{

CalculateGroupGPA();

}

[OnDeserialized]

private void AfterDeserialization(StreamingContext context)

{

FindTheBestStudent();

}

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

}

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

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

public interface ISerializable

{

void GetObjectData(SerializationInfo info,

StreamingContext context);

}

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

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

[Serializable]

public class Student: IComparable< Student>, ISerializable

{

void ISerializable.GetObjectData(SerializationInfo info,

StreamingContext ctx)

{

info.SetType(typeof (Student));

info.AddValue(" Name", _name);

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

}

 

private Student(SerializationInfo info, StreamingContext ctx)

{

_name = info.GetString(" Name");

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

}

 

public Student() { }

 

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

}






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.