Разработка приложений на языке C#. Полезные настройки. Особые спецификаторы формата, страница 36

men.Clear();  // Для убедительности

IFormatter fmt = new BinaryFormatter();

Stream stream = new FileStream ("../../List.bin", FileMode.Open);

men = (List<Man>)fmt.Deserialize(stream);

stream.Close();

Более того, если вставить атрибут [Serializable] перед объявлением класса List, то объект list этого класса также может быть записан в поток и прочитан из него. Сформулируйте различия при сериализации объектов men и list.

Хранение данных в формате SOAP

Чтобы познакомиться с еще одним чудом от W3C — протоколом SOAP (Simple Object Access Protocol), надо добавить ссылку на DLL. Поставьте фокус в узел References дерева файлов окна Solution Explorer и дайте команду Add Reference. В диалоге на вкладке .NET найдите строку System.Runtime.Serialization.Formatters.Soap.dll, нажмите кнопки Select, OK и добавьте директиву:

using System.Runtime.Serialization.Formatters.Soap;

К сожалению, generic-коллекции (каковой является наша коллекция men) не могут быть сериализованы в формате SOAP. Но выход очень прост. Почти все коллекции имеют метод ToArray. Он преобразует коллекцию в обычный массив, точнее создает массив на основе данных коллекции. Этот массив отлично сериализуется любым способом. Для проверки SOAP-сериализации введите следующий кодовый фрагмент:

Stream stream = new FileStream("../../List.soap", FileMode.Create);

IFormatter fmt = new SoapFormatter();

fmt.Serialize (stream, men.ToArray());

stream.Close();

Чтение можно осуществить симметричным способом:

men.Clear();

IFormatter fmt = new SoapFormatter();

Stream stream = new FileStream ("../../List.soap", FileMode.Open);

Man[] ma = (Man[])fmt.Deserialize(stream);

foreach(Man m in ma)

  men.Add(m);

stream.Close();

Интересно сравнить между собой форматы файлов List.bin и List.soap. Первый — действительно является двоичным форматом. Он не содержит разделителей, числовые данные имеют внутреннее (машинное) представление и, поэтому, с трудом читаются в текстовом виде. Второй — напоминает формат xml, но использует несколько другой стандарт, принятый для хранения и передачи сетевых сообщений при обработке XML Web-служб.

Как сохранить список в формате XML

Настоящий xml-формат файла можно получить с помощью класса XmlSerializer. Но эту технологию применить не так просто, как две предыдущие, из-за того, что наш список содержит коллекцию ссылок на объекты двух классов (Stud, Prof), производных от Man. Сначала покажем, как использовать XmlSerializer при выводе обычного однородного массива. В отличие от классов BinaryFormatter и SoapFormatter, которые автоматически сериализуют все данные, XmlSerializer пытается сохранить только public-данные (или открытые свойства) объекта. При этом:

·  Сериализуемый класс должен иметь default-конструктор.

·  Атрибут [Serializable] сериализуемому классу не нужен.

·  XmlSerializer отлично справляется с массивами объектов, но требует особых настроек при работе с коллекциями.

·  Атрибуты позволяют управлять структурой XML-документа.

Предположим, что нам надо сохранить массив объектов класса Address.

public class Address

{

[XmlAttribute]

public string name; // Это поле мы хотим видеть в виде атрибута, а не элемента (по умолчанию)

   [XmlElementAttribute(IsNullable = false)]

   public string city;   // Если city == null, то city не попадет в XML-файл (поле будет отсутствовать)

public string state;    // Обычное поле

public Address() { name = city = state = "N/A"; }

public Address (string n, string c, string s) { name = n; city = c; state = s; }

public override string ToString()

{

  return name + ";  City: " + city + ";  State : " + state;

}

}

Технология работы с объектами рассмотренных классов при записи массива показана в следующем фрагменте.

using System.Xml.Serialization;

public class Program

{

public static void TestXmlSerializer ()

{

  Console.Clear();

  Address[] addr = {

             new Address ("Don Box", "Redmont", "WA"),