Если у вас есть опыт использования XML-технологий, вы должны хорошо знать о том, что в документе XML очень важно гарантировать соответствие элементов набору правил, обеспечивающих "допустимость" данных. Следует понимать, что "допустимость" XML-документа не связана напрямую с синтаксической правильностью его XML-элементов (например, с требованием о том, что все открываемые элементы должны иметь закрывающие их дескрипторы). Скорее, допустимость документов связана с правилами форматирования (например, поле X должно быть атрибутом и не вложенным элементом), которые обычно задаются XML-схемой или DTD-файлом (файл определения типа документа),
По умолчанию все поля данных типа [Serializable] форматируются, как элементы, а не как XML-атрибуты. Для контроля того, как XmlSerializer компонует генерируемый XML-документ, следует указать для типов [Serializable] дополнительные атрибуты из пространства имен System.Xml.Serialization. В табл. 17.1 представлены некоторые из атрибутов, влияющих на кодирование XML-данных, передаваемых в поток.
Таблица 17.1. Атрибуты пространства имен System.Xml.Serialization, связанные с сериализацией объектов
| Атрибут | Описание |
|---|---|
| XmlAttributeAttribute | Член будет сохранен в виде XML-атрибута |
| XmlElementAttribute | Поле или свойство будут сохранены в виде XML-элемента |
| XmlEnumAttribute | Имя элемента перечня |
| XmlRootAttribute | Атрибут, контролирующий формат корневого элемента (пространство имен и имя элемента) |
| XmlTextAttribute | Свойство или поле должно сохраняться в виде XML-текста |
| XmlTypeAtttribute | Имя и пространство имен XML-типа |
Для примера давайте сначала выясним, как поля данных JamesBondCar сохраняются в XML-документе в настоящий момент.
‹?xml version="1.0" encodings="utf-8"?›
‹JamesBondCar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd=http://www.w3.org/2001/XMLSchema›
…
‹canFly›true‹/canFly›
‹canSubmerge›false
Если вы хотите указать пользовательское пространство имен XML, соответствующее JamesBondCar, и кодировать значения canFly и canSubmerge в виде XML-атрибутов, это можно сделать с помощью изменения определения JamesBondCar в C# следующим образом.
[Serializablе, XmlRoot(Namespace = "http://www.intertechtraining.com")]
public class JamesBondCar: Car {
…
[XmlAttribute]
public bool canFly;
[XmlAttribute]
public bool canSubmerge;
}
Это должно дать в результате следующий XML-документ (обратите внимание на открывающий элемент ‹JamesBondCar›).
‹?xml version="1.0" encodin="utf-8"?›
‹JamesBondCar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" canFly="true" canSubmerge="false"
xmlns="http://www.intertechtraining.com"›
…
‹/JamesBondCar›"
Конечно, есть множество других атрибутов, которые вы можете использовать для управления процессом генерирования XML-документа с помощью XmlSerializer. Чтобы ознакомиться со всеми опциями, выполните поиск информации о пространстве имен System.Xml.Serialization в документации .NET Framework 2.0 SDK
Сохранение коллекций объектов
Теперь вы знаете, как сохранить в потоке отдельный объект, и давайте выясним, как сохранить множество объектов. Заметим, что метод Serialize() интерфейса IFormatter не позволяет указать произвольное число объектов (а только один System.Object). Аналогично, возвращаемым значением Deserialize() тоже является один System.Object.
public interface IFormatter {
…
object Deserialize(System.IO.Stream serializationStream);
void Serialize(System.IO.Stream serializationStream, object graph);
}