Использование .Net, какие ограничения (если таковые имеются) существуют в использовании XmlSerializer? - PullRequest
8 голосов
/ 21 сентября 2008

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

Ответы [ 8 ]

22 голосов
/ 21 сентября 2008

Я обычно нахожу 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 (indexer в C #), которое принимает целое число, и у него должно быть открытое свойство Count типа integer. Параметр метода Add должен быть того же типа, который возвращается из свойства Item или одной из основ этого типа. Для классов, которые реализуют ICollection, значения для сериализации извлекаются из индексированного свойства Item, а не путем вызова GetEnumerator.

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

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

XmlSerializer.XmlSerializer (тип) XmlSerializer.XmlSerializer (Type, String)

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

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

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

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

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

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

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

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

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

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

3 голосов
/ 27 ноября 2008

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

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

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

Это занимает много времени при первом сериализации класса и требует кода с разрешениями для компиляции и записи на диск.

Один из способов обойти это - предварительно скомпилировать эти DLL с помощью инструмента sGen.exe, поставляемого с VS 2005+.

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

2 голосов
/ 21 сентября 2008

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

1 голос
/ 21 сентября 2008

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

1 голос
/ 21 сентября 2008

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

1 голос
/ 21 сентября 2008

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

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

0 голосов
/ 21 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...