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.
Чтобы познакомиться с еще одним чудом от 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-формат файла можно получить с помощью класса 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"),
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.