сериализация XML

Сериализация представляет собой процесс преобразования объекта в форму, подготовленную для передачи. Например, можно сериализовать объект и передать его по Интернету с использованием протокола HTTP между клиентом и сервером. И наоборот, при десериализации объект воссоздается из потока.

При XML-сериализации в поток XML сериализуются только открытые поля и значения свойств объекта. XML-сериализация не учитывает информацию о типе. Например, если имеется объект Book, который существует в пространстве имен Library, нет никакой гарантии, что он десериализуется в объект аналогичного типа.

Примечание.

XML-сериализация не выполняет преобразование методов, индексаторов, закрытых полей или свойств только для чтения (кроме коллекций только для чтения). Для сериализации всех полей и свойств объекта, как открытых, так и закрытых, используйте DataContractSerializer вместо XML-сериализации.

Центральным классом XML-сериализации является класс XmlSerializer, а наиболее важные методы в этом классе — Serialize и Deserialize. XmlSerializer создает файлы C# и компилирует их в файлы DLL для выполнения сериализации. Средство создания сериализатора XML (Sgen.exe) предназначено для создания таких сборок сериализации заранее, они будут развертываться вместе с приложением и повышать производительность при запуске. Поток XML, создаваемый XmlSerializer, соответствует рекомендациям для языка определения схемы XML (XSD) 1.0 консорциума W3C. Более того, создаваемые типы данных соответствуют документу "XML Schema Part 2: Datatypes".

Данные в объектах описываются с помощью конструкций языка программирования, например классов, полей, свойств, типов примитивов, массивов и даже встроенного XML в форме объектов XmlElement или XmlAttribute. Предусмотрена возможность создания собственных классов, аннотируемых атрибутами, или использования инструмента определения схемы XML для создания классов на основе существующей схемы XML.

При наличии схемы XML можно запустить инструмент определения схемы XML, чтобы создать набор классов со строгим типом схемы, которые аннотированы атрибутами. При сериализации экземпляра такого класса созданный XML соответствует схеме XML. Благодаря такому классу можно создать код с использованием объектной модели, которой легко управлять, и при этом гарантировать соответствие созданного XML схеме XML. Это альтернативный вариант использования других классов в .NET, например классов XmlReader и XmlWriter, для анализа и записи в поток XML. Дополнительные сведения см. в разделе XML-документы и данные. Эти классы позволяют анализировать любой поток XML. И наоборот, используйте XmlSerializer, когда предполагается, что поток XML соответствует известной схеме XML.

Атрибуты управляют потоком XML, который создан классом XmlSerializer, позволяя задавать пространство имен XML, имя элемента, имя атрибута потока XML и т. д. Дополнительные сведения об этих атрибутах и о том, как они управляют XML-сериализацией, см. в разделе Управление сериализацией XML с использованием атрибутов. Таблица атрибутов, используемых для управления созданным XML, представлена в разделе Атрибуты управления сериализацией XML.

Класс XmlSerializer может продолжать сериализовывать объект и создавать поток XML с кодировкой SOAP. Созданный XML соответствует разделу 5 документа консорциума World Wide Web Consortium с названием "Simple Object Access Protocol (SOAP) 1.1". Дополнительные сведения об этом процессе см. в статье "Практическое руководство. Сериализация объекта в виде XML-потока в кодировке SOAP". Таблица атрибутов, используемых для управления созданным XML, представлена в разделе Атрибуты управления сериализацией с кодировкой SOAP.

Класс XmlSerializer создает сообщения SOAP, созданные и переданные в XML-веб-службы. Для управления сообщениями SOAP можно применять атрибуты к классам, возвращаемым значениям, параметрам и полям, обнаруженным в файле XML-веб-службы (файл ASMX). Можно применять оба атрибута, указанные в списках "Атрибуты управления XML-сериализацией" и "Атрибуты управления сериализацией с кодировкой SOAP", поскольку XML-веб-служба использует либо литеральный стиль, либо стиль с кодировкой SOAP. Дополнительные сведения о применении атрибутов для управления XML, созданным XML-веб-службой, см. в разделе Сериализация XML с использованием XML-веб-служб. Дополнительные сведения о веб-службах XML и SOAP см. в разделе Настройка форматирования сообщений SOAP.

Вопросы безопасности в отношении приложений с XmlSerializer

При создании приложения, использующего класс XmlSerializer, помните о следующих особенностях и их последствиях.

  • XmlSerializer создает файлы C# (CS) и компилирует их в файлы DLL в каталоге, названном переменной среды TEMP. С помощью этих файлов DLL выполняется сериализация.

    Примечание.

    Такие сборки сериализации можно создавать заранее и подписать с помощью инструмента SGen.exe. Это не работает на сервере веб-служб. Другими словами, этот способ используется только для клиентов и сериализации вручную.

    Код и файлы DLL уязвимы для вредоносного процесса в момент создания и компиляции. Возможно, для двух или нескольких пользователей можно предоставить общий доступ к каталогу TEMP. Совместный доступ к каталогу TEMP представляет угрозу, если у двух учетных записей разные привилегии безопасности и приложение запускается из учетной записи с более высокими привилегиями с использованием XmlSerializer. В таком случае один из пользователей может нарушить безопасность компьютера, заменив либо компилируемый файл CS, либо файл DLL. Чтобы устранить такую уязвимость, нужно обязательно убедиться, что в каждой учетной записи на компьютере имеется отдельный профиль. По умолчанию переменная среды TEMP указывает на разные каталоги для каждой учетной записи.

  • Если злоумышленник отправляет непрерывный поток данных XML на веб-сервер (атака типа "отказ в обслуживании"), XmlSerializer продолжает обрабатывать данные, пока на их обработку не будут потрачены все ресурсы системы.

    Такой вид атаки блокируется, если используется компьютер с запущенными службами Internet Information Services (IIS) и приложение работает в среде IIS. В службах IIS используется логический элемент, который не обрабатывает потоки, размер которых больше заданного значения (по умолчанию 4 КБ). Если создается приложение, не использующее службы IIS и выполняющее сериализацию с помощью XmlSerializer, необходимо реализовать похожий логический элемент, который будет блокировать атаки типа "отказ в обслуживании".

  • XmlSerializer сериализует данные и запускает соответствующий код с использованием любого переданного ему типа.

    Вредоносный объект может представлять угрозу в двух случаях. Он может запустить вредоносный код или ввести его в файл C#, созданный XmlSerializer. Во втором случае теоретически существует вероятность того, что вредоносный объект может каким-либо способом ввести код в файл C#, созданный XmlSerializer. Несмотря на то что эта проблема была тщательно изучена и вероятность такой атаки минимальна, следует принять меры предосторожности, т. е. никогда не сериализовывать данные неизвестного и недоверенного типа.

  • Сериализованные конфиденциальные данные могут быть уязвимы.

    После того как XmlSerializer сериализовал данные, их можно сохранить в файл XML или в другое хранилище данных. Если хранилище данных доступно для других процессов или видно в интрасети или в Интернете, данные могут быть украдены и использованы с преступными намерениями. Например, если создается приложение, которое сериализует заказы, содержащие номера кредитных карт, такие данные очень важны. Чтобы предотвратить злонамеренное использование, всегда защищайте хранилище данных и принимайте все меры, чтобы сделать его закрытым.

Сериализация простого класса

В следующем примере кода показан базовый класс с открытым полем.

Public Class OrderForm
    Public OrderDate As DateTime
End Class
public class OrderForm
{
    public DateTime OrderDate;
}

При сериализации экземпляра этого класса этот процесс может выглядеть следующим образом.

<OrderForm>
    <OrderDate>12/12/01</OrderDate>
</OrderForm>

Дополнительные примеры XML-сериализации см. в разделе Примеры сериализации XML.

Элементы, которые можно сериализовать

С помощью класса XmlSerializer можно сериализовать следующие элементы:

  • Открытые свойства чтения/записи и поля открытых классов.

  • Классы, реализующие ICollection или IEnumerable.

    Примечание.

    Сериализуются только коллекции, а не открытые свойства.

  • Объекты XmlElement.

  • Объекты XmlNode.

  • Объекты DataSet.

Дополнительные сведения о сериализации и десериализации объектов см. в разделах Практическое руководство. Сериализация объекта и Практическое руководство. Десериализация объекта.

Преимущества XML-сериализации

Класс XmlSerializer обеспечивает всестороннее и гибкое управление сериализацией объекта как XML. При создании XML-веб-службы к классам и членам можно применять атрибуты управления сериализацией, чтобы выходные данные XML соответствовали определенной схеме.

Например, XmlSerializer позволяет:

  • Указать, нужно ли кодировать поле или свойство как атрибут или элемент.

  • Указать используемое пространство имен XML.

  • Указать имя элемента или атрибута, если имя поля или свойства неправильное.

Еще одним преимуществом XML-сериализации является отсутствие ограничений для разрабатываемых приложений, поскольку создаваемый поток XML соответствует определенной схеме. Допустим, имеется схема, которая используется для описания книг. В ней представлены такие элементы, как название, автор, издатель и номер ISBN. Можно разработать приложение, которое обрабатывает данные XML любым удобным способом, например как заказ книги или список книг. В любом случае единственным требованием является соответствие потока XML указанной схеме языка определения схемы XML (XSD).

Вопросы, связанные XML-сериализацией

При использовании класса XmlSerializer следует обратить внимание на следующие аспекты:

  • Инструмент Sgen.exe разработан только для создания сборок сериализации для обеспечения оптимальной производительности.

  • Сериализованные данные содержат только сами данные и структуру классов. Удостоверения типа и информация о сборке не сохраняются.

  • Могут быть сериализованы только открытые свойства и поля. Для свойств должны быть указаны открытые методы доступа (методы get и set). Если необходимо сериализовать закрытые данные, вместо XML-сериализации используйте класс DataContractSerializer.

  • Класс должен иметь конструктор без параметров, сериализуемый с помощью XmlSerializer.

  • Методы не могут быть сериализованы.

  • XmlSerializer может по-разному обрабатывать классы, реализующие IEnumerable или ICollection, если они соответствуют определенным требованиям, см. ниже.

    Класс, реализующий IEnumerable, должен реализовывать открытый метод Add, принимающий один параметр. Параметр метода Add должен соответствовать (быть полиморфным) типу, возвращаемому из свойства IEnumerator.Current, которое возвращается из метода GetEnumerator.

    Класс, реализующий ICollection в дополнение к IEnumerable (например, CollectionBase), должен иметь открытое индексированное свойство Item (индексатор в C#), которое принимает целое число, и должен иметь открытое свойство Count типа integer. Параметр, передаваемый методу Add, должен быть того же типа, что и возвращаемый из свойства Item, или быть одной из баз такого типа.

    Для классов, реализующих ICollection, сериализуемые значения извлекаются из индексированного свойства Item, а не путем вызова GetEnumerator. Кроме того, открытые поля и свойства не сериализуются, за исключением открытых полей, которые возвращают другой класс коллекции (реализующий ICollection). Дополнительные примеры XML-сериализации см. в разделе Примеры сериализации XML.

Сопоставление типа данных XSD

Документ W3C с названием XML Schema Part 2: Datatypes указывает простые типы данных, разрешенные в схеме языка определения схемы XML (XSD). Для большинства из них (например, int и decimal) существует соответствующий тип данных в .NET. Однако для некоторых типов данных XML соответствующий тип данных в .NET (например, тип данных NMTOKEN) не предусмотрен. В таких случаях при использовании инструмента определения схемы XML (инструмент определения схемы XML (Xsd.exe)) для создания классов из схемы к члену строкового типа применяется соответствующий атрибут, и его свойство DataType задается как имя типа данных XML. Например, если схема содержит элемент с именем "MyToken" с типом данных XML NMTOKEN, созданный класс может содержать член, см. пример ниже.

<XmlElement(DataType:="NMTOKEN")> _
Public MyToken As String
[XmlElement(DataType = "NMTOKEN")]
public string MyToken;

Аналогичным образом, при создании класса, который должен соответствовать определенной схеме XML (XSD), следует применить соответствующий атрибут и задать его свойство DataType как необходимое имя типа данных XML.

Полный список сопоставлений типов см. в свойстве DataType для любого из следующих классов атрибутов:

См. также