- •Тверской государственный технический университет
- •Сериализация.
- •1. Теоретическая часть.
- •1.1. Сериализация.
- •1.2. Десериализация.
- •1.3. Сериализация коллекций объектов.
- •1.3.1. Описание объекта
- •1.3.2. Роль объектных графов.
- •1.3.3. Настройка объектов для сериализации.
- •1.3.4. Главная форма приложения
- •1.3.5. Настройка фильтра диалогового окна для открытия файлов.
- •2. Указания к выполнению лабораторной работы
- •2.1. Задание на лабораторную работу
- •2.2. Содержание отчета по лабораторной работе
- •Литература:
1.2. Десериализация.
Действия при десериализация, в основном, обратны действиям, соответствующим сериализации. Следующий пример открывает поток в виде файла Me.dat, создает объект типа BinaryFormatter для считывания объекта и вызывает метод Deserialize(), позволяющий восстаовить состояние этого объекта. После этого считанные данные приводятся к типу Person, и на консоль выводятся возраст и вес:
public static void DeSerialize()
{
// На этот раз сначала открывается файл
FileStream s = File.Open ("Me.dat" , FileMode.Open, FileAccess.Read);
// BinaryFormatted используется для чтения объекта (объектов) из потока
BinaryFormatter bf = new BinaryFormatter() ;
// Десериализация объекта
object о = bf.Deserialize(s) ;
//Убеждаемся в том, что объект нужного нам типа
Person р = о as Person;
if(р!=null)
Console.WriteLine("DeSerialized Person aged: {0} weight: {1}",
p.Age,p.WeightInPounds);
// Закрытие потока
s.Close();
}
В самом начале создается экземпляр класса BinaryFormatter, который используется для десериализации данных из файла. Затем создается объект потока типа FileStream, который будет представлять поток файла. Этот поток создается с параметрами FileMode.Open, чтобы открыть файл, и FileAccess.Read для того, чтобы можно было считывать данные из открытого потока.
Самое интересное в программном коде заключается в вызове метода Deserialize(s) у форматера типа BinaryFormatter. Этот метод получает только лишь один аргумент в виде потока, из которого следует считывать данные. Метод читает данные в поисках полей данных (или свойств) сохраненного объекта и возвращает его в виде результата своей работы. Причем метод сам создает объект и инициализирует его сохраненными данными. Поэтому нам и не нужно инициализировать объект типа Person. В результате мы получаем объект типа Person и нам остается только привести типы. Но как же метод узнает класс создаваемого им объекта, который он десериализировал из потока? Дело в том, что информация о классе также сохраняется в потоке.
Объекты можно сохранять не только в файлах, но и в потоке памяти MemoryStream. Например, перед выполнением каких-либо расчетов можно сохранить состояние объекта в потоке памяти и восстановить это состояние после выполнения расчетов. В такие моменты потоки в памяти предоставляют всю мощь и скорость доступа.
Обычно, с помощью атрибута NonSerialized (не подлежащие сериализации) помечаются данные, которые получаются в результате вычислений, поскольку они могут быть вычислены по мере возникновения такой необходимости. В качестве примера можно привести класс, в котором вычисляются простые числа. Их вполне можно сохранять для увеличения скорости ответа при обращении к данному классу, однако сериализация и десериализация списка простых чисел не является необходимой, поскольку они всегда могут быть вычислены в момент обращения к классу. В других случаях некоторый член может иметь отношение только к данному экземпляру документа. Например, для объекта, который представляет документ, обрабатываемый редактором, потребуется сериализовать содержимое самого документа, но не текущую позицию, поскольку при очередной загрузке документа в качестве такой позиции просто используется начало документа.
