Вопрос

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

Причина моего любопытства заключается в том, почему BinaryFormatter способен десериализовать непосредственно в интерфейс, в то время как XmlSerializer - нет. Джон Скит в ответе на "приведение к нескольким (неизвестным типам) во время выполнения" предоставляет пример прямой двоичной сериализации в интерфейсе. Стэн Р. предоставил мне средства для достижения моей цели с помощью XmlSerializer в своем ответе на "Десериализация XML-объекта в интерфейс."

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

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

Решение

Причина, по которой двоичный форматировщик способен десериализовать непосредственно к типу интерфейса, заключается в том, что при первоначальной сериализации объекта в двоичный поток метаданные, содержащие информацию о типе и сборке, вставляются вместе с данными объекта.Это означает, что когда двоичный форматировщик десериализует объект, он знает его тип, создает правильный объект, и затем вы можете привести его к типу интерфейса, который реализует object.

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

Вот хороший пост, Сериализация .NET, сравнивая Двоичный форматировщик, Форматировщик мыла, и XmlSerializer - Сериализатор.Я рекомендую вам взглянуть на следующую таблицу, которая в дополнение к ранее упомянутым сериализаторам включает Сериализатор DataContractSerializer, Сериализатор NetDataContractSerializer и протобуф-сеть.

Serialization Comparison

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

Просто чтобы все взвесить...

Очевидное различие между ними - "двоичный файл против xml", но оно намного глубже, чем это:

  • поля (BinaryFormatter=bf) против публичный члены (обычно свойства) (XmlSerializer=xs)
  • тип-основанный на метаданных (bf) против основанного на контракте (xs)
  • версия-хрупкая (bf) против версии-толерантная (xs)
  • "график" (bf) против "дерева" (xs)
  • Специфичный для .NET (bf) против переносимого (xs)
  • непрозрачный (bf) против удобочитаемого (xs)

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

Невозможно обсудить, что больше;все метаданные типа в BinaryFormatter может сделать его больше.И XmlSerializer может очень хорошо работать со сжатием, таким как gzip.

Однако можно воспользоваться сильными сторонами каждого;например, у Google есть собственный формат сериализации данных с открытым исходным кодом - "буферы протокола".Это:

  • основанный на контракте
  • портативный (см. список реализаций)
  • допускаемая версия
  • основанный на дереве
  • непрозрачный (хотя существуют инструменты для отображения данных в сочетании с .proto)
  • как правило "сначала контракт", но некоторые реализации допускают неявные контракты, основанные на отражении

Но важно отметить, что это очень плотные данные (без метаданных типа, чисто двоичное представление, короткие теги, хитрости вроде кодировки с базовой длиной 7 вариантов) и очень эффективные в обработке (без сложной структуры xml, без строк для сопоставления с элементами и т.д.).

Возможно, я немного предвзят;Я поддерживаю одну из реализаций (включая несколько подходящих для C # / .NET), но вы заметите, что я не связал с Любой конкретная реализация;формат имеет свои собственные достоинства ;-p

XML-сериализатор создает XML, а также XML-схему (неявно).Он создаст XML, соответствующий этой схеме.

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

Сериализация во время выполнения (которая BinaryFormatter является частью) сериализует фактический .СЕТЕВЫЕ типы на другую сторону, поэтому, если вы отправляете List<int>, другая сторона получит List<int>.

Это, очевидно, работает лучше, если на другой стороне запущен файл .NET.

XmlSerializer сериализует тип, считывая все свойства типа, которые имеют как общедоступный метод получения, так и общедоступный метод установки (а также любые общедоступные поля).В этом смысле XmlSerializer сериализует / десериализует "общедоступный просмотр" экземпляра.

Двоичный форматировщик, напротив, сериализует тип путем сериализации "внутренних компонентов" экземпляра, т. е.его поля.Любые поля, которые не помечены как [Несериализованные], будут сериализованы в двоичный поток.Сам тип должен быть помечен как [Serializable], как и любые внутренние поля, которые также должны быть сериализованы.

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

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

http://www.nablasoft.com/alkampfer/index.php/2008/10/31/binary-versus-xml-serialization-size/

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