Поделиться через


Класс System.Xml.Serialization.XmlSerializer

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

Сериализация XML — это процесс преобразования открытых свойств и полей объекта в серийный формат (в данном случае в формат XML) для хранения или транспортировки. Десериализация повторно создает объект в исходном состоянии из выходных данных XML. Сериализация можно рассматривать как способ сохранения состояния объекта в потоке или буфере. Например, ASP.NET использует XmlSerializer класс для кодирования сообщений веб-службы XML.

Данные в объектах описываются с помощью конструкций языка программирования, например классов, полей, свойств, типов-примитивов, массивов и даже встроенного XML в форме объектов XmlElement или XmlAttribute. Вы можете создавать собственные классы, аннотировать атрибутами или использовать средство определения схемы XML (Xsd.exe) для создания классов на основе существующего документа определения схемы XML (XSD). Если у вас есть XML-схема, можно запустить Xsd.exe для создания набора классов, строго типизированных в схему и аннотированных атрибутами, которые соответствуют схеме при сериализации.

Для передачи данных между объектами и XML требуется сопоставление из конструкций языка программирования с схемой XML и из схемы XML в конструкции языка программирования. Такие XmlSerializer инструменты, как Xsd.exe, обеспечивают мост между этими двумя технологиями во время разработки и во время выполнения. Во время разработки используйте Xsd.exe для создания xml-документа схемы (XSD) из пользовательских классов или создания классов из данной схемы. В любом случае классы аннотируются с пользовательскими атрибутами, чтобы указать XmlSerializer , как сопоставить систему схемы XML и среду CLR. Во время выполнения экземпляры классов можно сериализовать в XML-документы, которые соответствуют заданной схеме. Аналогичным образом эти XML-документы можно десериализировать в объекты среды выполнения. Обратите внимание, что схема XML является необязательной и не требуется во время разработки или во время выполнения.

Созданный элемент управления XML

Для управления созданным XML можно применять специальные атрибуты к классам и членам. Например, чтобы указать другое имя XML-элемента, примените XmlElementAttribute его к общедоступному полю или свойству ElementName и задайте это свойство. Полный список аналогичных атрибутов см. в разделе Атрибуты, управляющие сериализацией XML. Вы также можете реализовать IXmlSerializable интерфейс для управления выходными данными XML.

Если созданный XML-код должен соответствовать разделу 5 документа консорциума Всемирного консорциума, протоколу простого доступа к объектам (SOAP) 1.1, необходимо создать XmlSerializer его с помощью XmlTypeMapping. Для дальнейшего управления кодированным XML-файлом SOAP используйте атрибуты, перечисленные в атрибутах, которые управляют сериализацией SOAP в кодировке SOAP.

XmlSerializer Используя преимущества работы с строго типизированными классами, и они по-прежнему имеют гибкость XML. С помощью полей или свойств типа или XmlNode в строго типизированных XmlElementXmlAttribute классах можно считывать части XML-документа непосредственно в XML-объекты.

При работе с расширяемыми XML-схемами можно также использовать XmlAnyElementAttribute атрибуты для XmlAnyAttributeAttribute сериализации и десериализации элементов или атрибутов, которые не найдены в исходной схеме. Чтобы использовать объекты, примените к полю, возвращающее массив объектов, или примените XmlAnyAttributeAttributeXmlAnyElementAttribute к полю, возвращающее массив XmlElementXmlAttribute объектов.

Если свойство или поле возвращает сложный объект (например, массив или экземпляр класса), XmlSerializer преобразует его в элемент, вложенный в рамках основного документа XML. Например, первый класс в следующем коде возвращает экземпляр второго класса.

Public Class MyClass
    Public MyObjectProperty As MyObject
End Class

Public Class MyObject
    Public ObjectName As String
End Class
public class MyClass
{
    public MyObject MyObjectProperty;
}
public class MyObject
{
    public string ObjectName;
}

Сериализованные выходные данные XML выглядят следующим образом:

<MyClass>
  <MyObjectProperty>
  <ObjectName>My String</ObjectName>
  </MyObjectProperty>
</MyClass>

Если схема содержит элемент, который является необязательным (minOccurs = "0") или если схема содержит значение по умолчанию, у вас есть два варианта. Один из вариантов — указать System.ComponentModel.DefaultValueAttribute значение по умолчанию, как показано в следующем коде.

Public Class PurchaseOrder
    <System.ComponentModel.DefaultValueAttribute ("2002")> _
    Public Year As String
End Class
public class PurchaseOrder
{
    [System.ComponentModel.DefaultValueAttribute ("2002")]
    public string Year;
}

Другим вариантом является использование специального шаблона для создания логического поля, распознаваемого пользователем XmlSerializer, и применения XmlIgnoreAttribute к полю. Шаблон создается в виде propertyNameSpecified. Например, если есть поле с именем MyFirstName, вы также создадите поле с именем MyFirstNameSpecified, которое указывает XmlSerializer , следует ли создать XML-элемент с именем MyFirstName. Это показано в следующем примере.

Public Class OptionalOrder
    ' This field's value should not be serialized
    ' if it is uninitialized.
    Public FirstOrder As String

    ' Use the XmlIgnoreAttribute to ignore the
    ' special field named "FirstOrderSpecified".
    <System.Xml.Serialization.XmlIgnoreAttribute> _
    Public FirstOrderSpecified As Boolean
End Class
public class OptionalOrder
{
    // This field should not be serialized
    // if it is uninitialized.
    public string FirstOrder;

    // Use the XmlIgnoreAttribute to ignore the
    // special field named "FirstOrderSpecified".
    [System.Xml.Serialization.XmlIgnoreAttribute]
    public bool FirstOrderSpecified;
}

Переопределение сериализации по умолчанию

Можно также переопределить сериализацию любого набора объектов и их полей и свойств, создав один из соответствующих атрибутов и добавив его в экземпляр XmlAttributes класса. Переопределение сериализации таким образом использует два варианта: сначала можно управлять сериализацией объектов, найденных в библиотеке DLL, даже если у вас нет доступа к источнику; во-вторых, можно создать один набор сериализуемых классов, но сериализовать объекты несколькими способами. Дополнительные сведения см. в XmlAttributeOverrides разделе "Класс и практическое руководство. Управление сериализацией производных классов".

Чтобы сериализовать объект, вызовите Serialize метод. Чтобы десериализировать объект, вызовите Deserialize метод.

Сведения о добавлении пространств имен XML в XML-документ см. в статье XmlSerializerNamespaces.

Примечание.

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

Для десериализации объекта необходимо иметь разрешение на запись во временный каталог (как определено переменной среды TEMP).

Динамически созданные сборки

Чтобы повысить производительность, инфраструктура сериализации XML динамически создает сборки для сериализации и десериализации указанных типов. Инфраструктура находит и повторно использует эти сборки. Это поведение происходит только при использовании следующих конструкторов:

XmlSerializer.XmlSerializer(Type)

XmlSerializer.XmlSerializer(Type, String)

При использовании любого из других конструкторов несколько версий одной сборки создаются и никогда не выгружаются, что приводит к утечке памяти и низкой производительности. Проще всего использовать один из ранее упоминание двух конструкторов. В противном случае необходимо кэшировать сборки в виде Hashtable, как показано в следующем примере.

Hashtable serializers = new Hashtable();

// Use the constructor that takes a type and XmlRootAttribute.
XmlSerializer s = new XmlSerializer(typeof(MyClass), myRoot);

// Implement a method named GenerateKey that creates unique keys
// for each instance of the XmlSerializer. The code should take
// into account all parameters passed to the XmlSerializer
// constructor.
object key = GenerateKey(typeof(MyClass), myRoot);

// Check the local cache for a matching serializer.
XmlSerializer ser = (XmlSerializer)serializers[key];
if (ser == null)
{
    ser = new XmlSerializer(typeof(MyClass), myRoot);
    // Cache the serializer.
    serializers[key] = ser;
}

// Use the serializer to serialize or deserialize.
Dim serializers As New Hashtable()

' Use the constructor that takes a type and XmlRootAttribute.
Dim s As New XmlSerializer(GetType([MyClass]), myRoot)

' Implement a method named GenerateKey that creates unique keys
' for each instance of the XmlSerializer. The code should take
' into account all parameters passed to the XmlSerializer
' constructor.
Dim key As Object = GenerateKey(GetType([MyClass]), myRoot)

' Check the local cache for a matching serializer.
Dim ser As XmlSerializer = CType(serializers(key), XmlSerializer)

If ser Is Nothing Then
    ser = New XmlSerializer(GetType([MyClass]), myRoot)
    ' Cache the serializer.
    serializers(key) = ser
End If

' Use the serializer to serialize or deserialize.

Сериализация массива и универсального списка

Не XmlSerializer удается сериализовать или десериализировать следующее:

Сериализация перечислений без знака Long

XmlSerializer Невозможно создать экземпляр для сериализации перечисления, если указаны следующие условия: перечисление имеет тип unsigned long (ulongв C#) и перечисление содержит любой элемент со значением, превышающим 9223 372 036 854 775 807. Например, не удается сериализовать следующее.

public enum LargeNumbers: ulong
{
    a = 9223372036854775808
}
// At run time, the following code will fail.
xmlSerializer mySerializer=new XmlSerializer(typeof(LargeNumbers));

Устаревшие типы

Класс XmlSerializer не сериализует объекты, помеченные как [Obsolete].