Сохранение объектов представляет собой определенную проблему. Связано это с тем, что обычно переменные объекта являются недоступными в программе. Для решения этой проблемы создано пространство имен System.Runtime.Serialization с классами, используемыми для сериализации и десериализации объектов.
Сериализация — это процесс преобразования объекта или графа объектов в линейную последовательность байтов для сохранения с помощью потока.
Десериализация — это процесс изъятия сохраненных сведений и создания из них объектов.
Для того чтобы объекты можно было сериализовать, его класс должен быть помечен атрибутом [Serializable].
По умолчанию CLR не предполагает, что объекты будут сохраняться в каком-либо хранилище (например, в файле на диске).
Для сериализации объекта нужно выполнить следующие шаги:
• Пометить сериализуемый класс атрибутом [Serializable].
• Создать байтовый поток.
• Создать объект класса BinaryFormatter, управляющий сериализацией.
• Вызвать метод Serialize() этого объекта для выполнения сериализации.
Для десериализации объектов нужно вместо метода Serialize() выполнить метод Deserialize() и привести воостанавливаемые объекты к требуемому типу.
// Сохранение объектов
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
class Customer
{
private int CustomerNumber; // N покупателя
private string CustomerName; // Имя покупателя
private string CustomerCountry; // Страна
public Customer (int Number, string Name, string Country)
{
this.CustomerNumber = Number;
this.CustomerName = Name;
this.CustomerCountry = Country;
}
public void WriteCustomer()
{
Console.WriteLine("Customer Number: " + CustomerNumber);
Console.WriteLine("Customer Name: " + CustomerName);
Console.WriteLine("Customer Country: " + CustomerCountry);
}
}
class SaveObj
{
public static void Main()
{
FileStream fs;
Customer Customer1 = new Customer (1, "Aлен Дилон", "Франция");
Customer Customer2 = new Customer (2, "Иванов", "Россия");
Customer1.WriteCustomer();
Customer2.WriteCustomer();
// Создание потока
fs = new FileStream ("c:\\Temp\\Customer.dat", FileMode.Create);
// Воспользуемся поддержкой двоичного форматирования в CLR
BinaryFormatter sf = new BinaryFormatter();
// Сохраним объект в файле в двоичном виде
sf.Serialize (fs, Customer1);
sf.Serialize (fs, Customer2);
fs.Close();
// Восстановим из файла сериализованный объект
fs = new FileStream ("c:\\Temp\\Customer.dat", FileMode.Open);
Customer NewCustomer1 = (Customer)sf.Deserialize (fs);
NewCustomer1.WriteCustomer();
Customer NewCustomer2 = (Customer)sf.Deserialize (fs);
NewCustomer2.WriteCustomer();
}
}
Если объект должен использоваться в другом приложении, лучшим выбором может оказаться не двоичный формат, а формат протокола SOAP (в виде XML-файла). SOAP – простой протокол доступа к объектам.
Для реализации этой задачи нужно:
• Вместо пространства имен System.Runtime.Serialization.Formatters.Binary использовать System.Runtime.Serialization.Formatters.Soap.
• Вместо класса BinaryFormatter использовать класс SoapFormatter.
• Файл создавать с расширением xml (необязательно).
// Сохранение объектов при помощи протокола SOAP
using System;
using System.IO;
using System.Runtime.Serialization;
// using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
[Serializable]
class Customer
{
private int CustomerNumber; // N покупателя
private string CustomerName; // Имя покупателя
private string CustomerCountry; // Страна
public Customer (int Number, string Name, string Country)
{
this.CustomerNumber = Number;
this.CustomerName = Name;
this.CustomerCountry = Country;
}
public void WriteCustomer()
{
Console.WriteLine("Customer Number: " + CustomerNumber);
Console.WriteLine("Customer Name: " + CustomerName);
Console.WriteLine("Customer Country: " + CustomerCountry);
}
}
class SaveObj
{
public static void Main()
{
FileStream fs;
Customer Customer1 = new Customer(1, "Aлен Дилон", "Франция");
Customer Customer2 = new Customer(2, "Иванов", "Россия");
Customer1.WriteCustomer();
Customer2.WriteCustomer();
// Создание потока
// fs = new FileStream ("c:\\Temp\\Customer.dat", FileMode.Create);
fs = new FileStream ("c:\\Temp\\Customer.xml", FileMode.Create);
// Воспользуемся поддержкой SOAP форматирования
// BinaryFormatter sf = new BinaryFormatter();
SoapFormatter sf = new SoapFormatter();
// Сохраним объект в файле в двоичном виде
sf.Serialize (fs, Customer1);
sf.Serialize (fs, Customer2);
fs.Close();
// Восстановим из файла сериализованный объект
fs = new FileStream ("c:\\Temp\\Customer.xml", FileMode.Open);
Customer NewCustomer1 = (Customer)sf.Deserialize (fs);
NewCustomer1.WriteCustomer();
Customer NewCustomer2 = (Customer)sf.Deserialize (fs);
NewCustomer2.WriteCustomer();
}
}
Классы SoapFormatter и BinaryFormatter предоставляют возможности для сериализации не только отдельных объектов, но и более сложных структур, например хеш-таблиц.
Такие структуры должны реализовывать интерфейс ISerializable. Реализация интерфейса ISerializable необходима классу в том случае, если он хочет управлять обработкой своей сериализации. Все коллекции FCL реализуют указанный интерфейс.
Пример сериализации хеш-таблицы.
using System;
using System.IO;
using System.Collections;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public class App
{
[STAThread]
static void Main()
{
Serialize();
Deserialize();
}
static void Serialize()
{
FileStream fs;
// Создать хеш-таблицу с ключем и полем данных.
Hashtable addresses = new Hashtable();
addresses.Add ("Сергей", "Москва, ул Пирогова, д.17, кв.25");
addresses.Add ("Юлия", "Новгород, ул.Космонавтов, д. 24");
addresses.Add ("Николай", "Тула, пр-т Ленина, д.134, кв. 76");
fs = new FileStream ("C:\\Temp\\DataFile.dat", FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
try
{
bf.Serialize (fs, addresses);
}
catch (SerializationException e) // в пространстве System.Runtime.Serialization
{
Console.WriteLine ("Ошибка сериализации: " + e.Message);
throw;
}
finally
{
fs.Close();
}
}
static void Deserialize()
{
FileStream fs;
Hashtable addresses = null;
// Open the file containing the data that you want to deserialize.
fs = new FileStream ("C:\\Temp\\DataFile.dat", FileMode. Open);
try
{
BinaryFormatter bf = new BinaryFormatter();
addresses = (Hashtable)bf.Deserialize(fs);
}
catch (SerializationException e)
{
Console.WriteLine("Ошибка десериализации: " + e.Message);
throw;
}
finally
{
fs.Close();
}
foreach (DictionaryEntry de in addresses)
{
Console.WriteLine("{0} живет в городе {1}.", de.Key, de.Value);
}
}
}
Другой способ сохранения объектов (без сериализации).
С помощью открытых методов Get…() получать значения полей объекта, записывать их в файл. При восстановлении объекта считывать поля из файла и подавать их значения в конструктор. Для полей объекта, которые не инициализируются конструктором, использовать методы Set…().
Дата: 2019-02-02, просмотров: 271.