Сегодня хочу рассказать о такой замечательной и полезной вещи в языке программирования c#, как сериализация пользовательских объектов. Сериализацией называется перевод каких-либо данных в последовательность битов. Соответственно, обратный процесс восстановления исходных данных является десериализация.
Представим ситуацию, наша программа запущена, работает отлично и производит какие-то вычисления или взаимодействует с пользователем. Рано или поздно приложение завершается, корректно или нет (вылетает исключение). При этом все данные хранились в памяти компьютера и теперь они потеряны. А нам допустим хотелось бы сохранять в какой-то момент времени информацию на жестком диске. Так вот, в данном вопросе нам и поможет сериализация языка c#, для записи и чтения определенных структур данных в файл.
Для примера, пусть наше приложение содержит инфу о студентах ВУЗа. Создадим два класса Student и FIO. Объект Student будет содержать поля course (курс) , faculty (факультет) и экземпляр класса FIO (личная информация о студенте). Чтобы не усложнять, личной информацией о студенте будет только имя(firstName) и фамилия (secondName).
-
-
//information about student
-
public class Student
-
{
-
public Student() { }
-
-
private int course;
-
private string faculty;
-
private FIO info;
-
}
-
-
//personal information
-
public class FIO
-
{
-
public FIO() { }
-
-
private string firstName;
-
private string secondName;
-
}
Студентов ВУЗа много, поэтому создадим список Student’ов :
-
List<Student> students = new List<Student>();
Теперь у нас есть коллекция объектов, можем её сериализовать. Когда я сохраняю данные в файл, обычно я создаю объект для всех сущностей, которые должны быть сериализованы:
-
public class SerializableObject
-
{
-
private List<Student> students;
-
-
public List<Student> Students
-
{
-
get { return this.students; }
-
set { this.students = value; }
-
}
-
-
public SerializableObject() { }
-
}
Наш класс хранит ссылку на все объекты для сериализации. Т.е. всё, что необходимо сохранить — это список студентов. Теперь давайте напишем методы, которые будут выполнять сериализацию и десериализацию объекта SerializableObject соответственно в и из файла. Поместим их в класс MySerializer:
-
using System.IO;
-
using System.Runtime.Serialization;
-
using System.Runtime.Serialization.Formatters.Binary;
-
-
public class MySerializer
-
{
-
public MySerializer() { }
-
-
public void SerializeObject(string fileName, SerializableObject objToSerialize)
-
{
-
FileStream fstream = File.Open(fileName, FileMode.Create);
-
BinaryFormatter binaryFormatter = new BinaryFormatter();
-
binaryFormatter.Serialize(fstream, objToSerialize);
-
fstream.Close();
-
}
-
-
public SerializableObject DeserializeObject(string fileName)
-
{
-
SerializableObject objToSerialize = null;
-
FileStream fstream = File.Open(fileName, FileMode.Open);
-
BinaryFormatter binaryFormatter = new BinaryFormatter();
-
objToSerialize = (SerializableObject)binaryFormatter.Deserialize(fstream);
-
fstream.Close();
-
return objToSerialize;
-
}
-
}
Это еще не всё, что необходимо для корректной работы нашего примера, к сожалению. Для того, чтобы данные сериализовались (десериализовались) верно, наш класс SerializableObject должен реализовать интерфейс ISerializable, а так же Serializable атрибут. Плюс для корректной десериализации надо добавить еще один конструктор. Смотрим код:
-
[Serializable]
-
public class SerializableObject : ISerializable
-
{
-
private List<Student> students;
-
-
public List<Student> Students
-
{
-
get { return this.students; }
-
set { this.students = value; }
-
}
-
-
public SerializableObject() { }
-
-
public SerializableObject(SerializationInfo sInfo, StreamingContext contextArg)
-
{
-
this.students = (List<Student>)sInfo.GetValue(«Students», typeof(List<Student>));
-
}
-
-
public void GetObjectData(SerializationInfo sInfo, StreamingContext contextArg)
-
{
-
sInfo.AddValue(«Students», this.students);
-
}
-
}
Поскольку объекты Student и FIO будут тоже сериализоваться, для их классов также реализуем ISerializable, плюс добавляем атрибут Serializable. Вот что должно получиться:
-
[Serializable]
-
public class Student : ISerializable
-
{
-
public Student() { }
-
-
public Student(SerializationInfo sInfo, StreamingContext contextArg)
-
{
-
this.course = (int)sInfo.GetValue(«Course», typeof(int));
-
this.faculty = (string)sInfo.GetValue(«Faculty», typeof(string));
-
this.info = (FIO)sInfo.GetValue(«FIO», typeof(FIO));
-
}
-
-
public void GetObjectData(SerializationInfo sInfo, StreamingContext contextArg)
-
{
-
sInfo.AddValue(«Course», this.course);
-
sInfo.AddValue(«Faculty», this.faculty);
-
sInfo.AddValue(«FIO», this.info);
-
}
-
-
private int course;
-
private string faculty;
-
private FIO info;
-
}
-
-
[Serializable]
-
public class FIO : ISerializable
-
{
-
public FIO() { }
-
-
public FIO(SerializationInfo sInfo, StreamingContext contextArg)
-
{
-
this.firstName = (string)sInfo.GetValue(«FirstName», typeof(string));
-
this.secondName = (string)sInfo.GetValue(«SecondName»,typeof(string));
-
}
-
-
public void GetObjectData(SerializationInfo sInfo, StreamingContext contextArg)
-
{
-
sInfo.AddValue(«FirstName», this.firstName);
-
sInfo.AddValue(«SecondName», this.secondName);
-
}
-
-
private string firstName;
-
private string secondName;
-
}
Наконец-то дождались, мы на финишной прямой. Теперь для сохранения в файл нашего списка студентов вызовем SerializeObject метод, а для извлечения из файла — DeserializeObject класса MySerializer:
-
List<Student> students = new List<Student>();
-
-
SerializableObject obj = new SerializableObject();
-
obj.Students = students;
-
-
MySerializer serializer = new MySerializer();
-
serializer.SerializeObject(«output.txt», obj);
-
-
obj = serializer.DeserializeObject(«output.txt»);
-
students = obj.Students;
Это пожалуй всё о сериализации пользовательского объекта в бинарный файл языка c#. Надеюсь статья оказалась познавательной для Вас.