При использовании .Net какие ограничения (если таковые имеются) существуют при использовании XmlSerializer?

StackOverflow https://stackoverflow.com/questions/109318

  •  01-07-2019
  •  | 
  •  

Вопрос

При использовании .Net какие ограничения (если таковые имеются) существуют при использовании XmlSerializer?Например, можете ли вы сериализовать изображения в XML?

Это было полезно?

Решение

XmlSerializer имеет несколько недостатков.

  1. Он должен знать все сериализуемые типы.Вы не можете передать ему что-то через интерфейс, который представляет тип, который не знает сериализатор.
  2. Он не может делать циклические ссылки.
  3. Он будет сериализовать один и тот же объект несколько раз, если на него несколько раз ссылаются в графе объектов.
  4. Невозможно обработать сериализацию частных полей.

Я (по глупости) написал свой собственный сериализатор, чтобы обойти некоторые из этих проблем.Не делай этого;это большая работа, и через несколько месяцев вы обнаружите в ней небольшие ошибки.Единственное, что я получил при написании собственного сериализатора и форматтера, — это лучшее понимание мелочей, связанных с сериализацией графа объектов.

Я нашел Нетдатаконтрактсериализатор когда вышел WCF.Он делает все, что описано выше, чего не делает XmlSerializer.Он управляет сериализацией аналогично XmlSerializer.Различные свойства или поля украшаются атрибутами, чтобы сообщить сериализатору, что сериализовать.Я заменил написанный мной собственный сериализатор на NetDataContractSerializer и был очень доволен результатами.Я очень рекомендую это.

Другие советы

Обычно я считаю, что XmlSerializer — плохой выбор для любого POCO, который представляет собой нечто большее, чем просто DTO.Если вам нужен конкретный XML, вы можете пойти по маршруту Xml*Attribute и/или IXmlSerializable, но у вас останется довольно искаженный объект.

Для некоторых целей это по-прежнему очевидный выбор, даже несмотря на свои ограничения.Но для простого хранения и перезагрузки данных я обнаружил, что BinaryFormatter — гораздо более простой выбор с меньшим количеством ошибок.

Вот список некоторых неприятностей, связанных с XmlSerializer: большинство из них меня укусили в тот или иной момент, другие я нашел на сайте MSDN:

  • Требуется общедоступный конструктор без аргументов.
  • Сериализует только общедоступные свойства и поля для чтения/записи.
  • Требуется знать все типы
  • На самом деле вызывает get_* и set_*, поэтому проверка и т. д.будет запущен.Это может быть хорошо или плохо (подумайте также о порядке вызовов)
  • Будет сериализовать только коллекции IEnumerable или ICollection, соответствующие определенным правилам.

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

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

  • Не сериализует IDictionary
  • Использует динамически создаваемые сборки, которые могут не выгружаться из домена приложения.

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

Xmlserializer.xmlserializer (type) xmlserializer.xmlserializer (тип, строка)

Если вы используете любой другой конструктор, создается несколько версий одной и той же сборки, которые никогда не выгружаются, что приводит к утечке памяти и снижению производительности.

  • Невозможно сериализовать ArrayList[] или List<T>[]
  • Имеет и другие странные крайние случаи

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

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

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

  • Требуется чтение .InnerException, чтобы получить полезную информацию об ошибках.

Другая проблема заключается в том, что вызов конструктора XmlSerializer скомпилирует код во время выполнения и создаст временную DLL (в папке %temp%) с кодом для десериализации.

Посмотреть код можно, если добавить в app.config следующие строки:

  <system.diagnostics>
    <switches>
      <add name="XmlSerialization.Compilation" value="4"/>
    </switches>
  </system.diagnostics>

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

Чтобы обойти эту проблему, необходимо предварительно скомпилировать эти DLL с помощью инструмента sGen.exe, который входит в состав VS 2005+.

Посмотрите здесь для получения дополнительной информации.

Не уверен, что есть какие-то ограничения..Но в XmlSerialization в .NET 1.1 была ошибка утечки памяти, вам как бы пришлось создать объект сериализатора кэша, чтобы обойти эту проблему...На самом деле, я не уверен, исправлена ​​ли эта проблема в .net 2.0 или новее...

Любой класс, который вы пишете, теоретически может быть передан через XmlSerializer.Однако у него есть доступ только к общедоступным полям, а классы необходимо пометить правильными атрибутами (например,XmlАтрибуте).Даже в базовом фреймворке не все поддерживает XmlSerializer.Например, System.Collections.Generic.Dictionary<>.

Единственное ограничение, о котором я могу думать, заключается в том, что XmlSerialization отключена;это означает, что любые свойства класса, которые вы не хотите сериализовать, ДОЛЖНЫ быть украшены [XmlIgnore].В отличие от DataContractSerializer, где все свойства являются добровольными, вы должны явно объявить атрибуты включения.Вот хороший записать.

Изображения или их двоичные массивы сериализуются как текст в кодировке Base64 с помощью XmlSerializer.

Например, вы не можете сериализовать классы, реализующие интерфейс IDictionary.

Для коллекций необходим метод Add, принимающий один аргумент.Если вам просто нужен текстовый формат, а не XML, вы можете попробовать JSON.Я разработал один для .NET, JsonExСериализатор, а также есть другие доступные на http://www.json.org.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top