Сохранение коллекций объектов
Сохранение коллекций объектов
Теперь вы знаете, как сохранить в потоке отдельный объект, и давайте выясним, как сохранить множество объектов. Заметим, что метод Serialize() интерфейса IFormatter не позволяет указать произвольное число объектов (а только один System.Object). Аналогично, возвращаемым значением Deserialize() тоже является один System.Object.
public interface IFormatter {
…
object Deserialize(System.IO.Stream serializationStream);
void Serialize(System.IO.Stream serializationStream, object graph);
}
Напомним, что System.Object фактически представляет весь объектный граф. Поэтому при передаче объекта, обозначенного атрибутом [Serializable] и содержащего другие объекты [Serializable], будет сохранен сразу весь набор объектов. Большинство типов, находящихся в рамках пространства имен System.Collections и System.Collections.Generic, уже обозначены атрибутом [Serializable]. Таким образом, чтобы сохранить набор объектов, просто добавьте этот набор в контейнер (например, в ArrayList или List‹›) и выполните сериализацию полученного объекта в подходящий поток.
Предположим, что в класс JamesBondCar был добавлен конструктор с двумя аргументами, чтобы можно было установить некоторые начальные данные состояния (обратите внимание на то, что конструктор, заданный по умолчанию, был возвращен на место в соответствии с требованиями XmlSerializer),
[Serializable,
XmlRoot(Namespace = "http://www.intartechtraining.com")]
public class JamesBondCar: Car {
public JamesBondCar(bool skyWorthy, bool seaWorthy) {
canFly = skyWorthy; canSubmerge = seaWorthy;
}
// Для XmlSerializer нужен конструктор, заданный по умолчанию!
public JamesBondCar(){}
…
}
При этом вы сможете сохранить любое число объектов JamesBondCar так.
static void Main(string[] args) {
…
// Сохранение объекта List‹› с набором JamesBondCar.
List‹JamesBondCar› myCars = new List‹JamesBondCar›();
myCars.Add(new JamesBondCar(true, true));
myCars.Add(new JamesBondCar(true, false));
myCars.Add(new JamesBondCar(false, true));
myCars.Add(new JamesBondCar(false, false));
fStream = new FileStream("CarCollection.xml", FileMode.Create, FileAccess.Write, FileShare.None);
xmlFormat = new XmlSerializer(typeof(List‹JamesBondCar›), new Type[] {typeof(JamesBondCar), typeof(Car), typeof(Radio)});
xmlFormat.Serialize(fStream, myCars);
fStream.Close();
Console.ReadLine();
}
Снова обращаем внимание на то, что по причине использования XmlSerializer требуется указать информацию типа для каждого из объектов, вложенных в корневой объект (которым в данном случае является List‹›). При использовании BinaryFormatter или SoapFormatter программная логика будет еще проще.
statiс void Main (string[] args) {
…
// Сохранение объекта List‹›(myCars) в двоичном формате.
list‹JamesBondCar› myCars = new List‹JamesBondCar›();
…
BinaryFormatter binFormat = new BinaryFormatter();
Stream fStream = new FileStream("AllMyCars.dat", FileMode.Create, FileAccess.Write, FileShare.None);
binFormat.Serialize(fStream, myCars);
fStream.Close();
Console.ReadLine();
}
Превосходно! К этому моменту вам должно быть понятно, как использовать сервис сериализации объектов для упрощения процесса сохранения и восстановления данных вашего приложения. Теперь давайте выясним, как использовать пользовательские настройки процесса сериализации.
Исходный код. Проект SimpleSerialize размещен в подкаталоге, соответствующем главе 17.