Каковы различия между XmlSerializer и BinaryFormatter
На прошлой неделе я потратил большую часть времени на сериализацию. За это время я нашел много примеров, использующих BinaryFormatter или XmlSerializer. К сожалению, я не нашел примеров, подробно описывающих различия между ними.
Генезис моего любопытства заключается в том, почему BinaryFormatter способен десериализоваться непосредственно на интерфейс, в то время как XmlSerializer – нет. Джон Скит в ответ на « отбрасывание нескольким (неизвестным типам) во время выполнения » предоставляет пример прямой двоичной сериализации для интерфейса. Стэн Р. предоставил мне средства для достижения моей цели, используя XmlSerializer в его ответе на « десериализация XML-интерфейса на интерфейс ».
Помимо очевидного BinaryFormatter использует двоичную сериализацию, в то время как XmlSerializer использует XML, я хотел бы более полно понять фундаментальные различия. Когда использовать одно или другое и за и против каждого.
Причина, по которой двоичный форматировщик может десериализоваться непосредственно на тип интерфейса, заключается в том, что когда объект изначально сериализуется в бинарный stream, метаданные, содержащие информацию о типе и сборке, застревают в данных объекта. Это означает, что когда бинарный форматир десериализует объект, он знает его тип, строит правильный объект, и затем вы можете применить его к типу интерфейса, который реализует объект.
Сериализатор XML с другой стороны просто сериализуется в схему и только сериализует общедоступные поля и значения объекта, а другую информацию о типе (например, интерфейсы типа реализует).
Вот хороший пост, .NET Serialization , сравнивающий BinaryFormatter , SoapFormatter и XmlSerializer . Я рекомендую вам взглянуть на следующую таблицу, которая помимо ранее упомянутых сериализаторов включает DataContractSerializer , NetDataContractSerializer и protobuf-net .
Просто взвесить …
Очевидное различие между ними – «двоичный vs xml», но он намного глубже:
- поля (
BinaryFormatter
= bf) vs public members (обычно свойства) (XmlSerializer
= xs) - тип-метаданные (bf) и контрактные (xs)
- версия-хрупкая (bf) и версия-толерантная (xs)
- “graph” (bf) vs “tree” (xs)
- .NET specific (bf) vs portable (xs)
- непрозрачный (bf) и понятный для человека (xs)
Как обсуждение того, почему BinaryFormatter
может быть хрупким, см. Здесь .
Невозможно обсуждать, что больше; все метаданные типа в BinaryFormatter
могут сделать его больше. И XmlSerializer
может работать очень с сжатием, как gzip.
Тем не менее, можно взять сильные стороны каждого; например, Google имеет открытый формат собственной сериализации данных, «буферы протокола». Это:
- контрактный
- переносной (см. список реализации )
- Версия для толерантных
- древовидный
- непрозрачные (хотя есть инструменты для отображения данных в сочетании с .proto)
- обычно « контракт сначала », но некоторые реализации позволяют заключать контракты на основе отражения
Но важно, что это очень плотные данные (метаданные типа, чистое двоичное представление, короткие tags, трюки, такие как кодирование с вариантной длиной базы-7) и очень эффективные для обработки (без сложной структуры xml, без строк для соответствия членам и т. Д.). ).
Я мог бы быть немного предвзятым; Я поддерживаю одну из реализаций (в том числе несколько подходящих для C # /. NET), но вы заметите, что я не связан с какой-либо конкретной реализацией; формат стоит по своим достоинствам; -p
Сериализатор XML создает XML, а также XML-схему (неявно). Он будет создавать XML, который соответствует этой схеме.
Одним из следствий является то, что он не будет сериализовать что-либо, что невозможно описать в XML-схеме. Например, нет способа различать список и массив в XML-схеме, поэтому XML-схема, создаваемая сериализатором, может быть интерпретирована в любом случае.
Сериализация времени выполнения (в которую входит BinaryFormatter
) сериализует реальные типы .NET с другой стороны, поэтому, если вы отправляете List
, другая сторона получит List
.
Это очевидно работает лучше, если другая сторона работает .NET.
XmlSerializer сериализует тип, читая все свойства этого типа, которые имеют как публичный геттер, так и публичный сеттер (а также любые общедоступные поля). В этом смысле XmlSerializer сериализует / десериализует «общеansible вид» экземпляра.
Бинарный форматтер, напротив, сериализует тип, сериализуя «внутренности» экземпляра, т. Е. Его поля. Любые поля, которые не помечены как [NonSerialized], будут сериализованы в двоичный stream. Сам тип должен быть помечен как [Serializable], как и любые внутренние поля, которые также должны быть сериализованы.
Я думаю, что одним из самых важных является то, что двоичная сериализация может сериализовать как публичные, так и частные члены, тогда как другая работает только с публичными.
Здесь он дает очень полезное сравнение между этими двумя размерами. Это очень важная проблема, потому что вы можете отправить свой сериализованный объект на удаленную машину.
http://www.nablasoft.com/alkampfer/index.php/2008/10/31/binary-versus-xml-serialization-size/