Сериализация
Примечание.
Это содержимое перепечатывается разрешением Pearson Education, Inc. из руководства по проектированию платформы: соглашения, идиомы и шаблоны для повторно используемых библиотек .NET, 2-го выпуска. Этот выпуск был опубликован в 2008 году, и книга с тех пор была полностью пересмотрена в третьем выпуске. Некоторые сведения на этой странице могут быть устаревшими.
Сериализация представляет собой процесс преобразования объекта в формат, подготовленный для сохранения и передачи. Например, можно сериализовать объект, передать его через Интернет с помощью HTTP и десериализировать его на целевом компьютере.
Платформа .NET Framework предусматривает три основные технологии сериализации, оптимизированные для различных сценариев сериализации. В следующей таблице перечислены эти технологии и основные типы платформ, связанные с этими технологиями.
Имя технологии | Основные типы | Сценарии |
---|---|---|
Сериализация контракта данных | DataContractAttribute DataMemberAttribute DataContractSerializer NetDataContractSerializer DataContractJsonSerializer ISerializable |
Общее сохранение Веб-службы JSON |
Сериализация XML | XmlSerializer | Формат XML с полным контролем над формой XML-кода |
Сериализация времени выполнения (двоичная и SOAP-сериализация) | SerializableAttribute ISerializable BinaryFormatter SoapFormatter |
Удаленное взаимодействие .NET |
✔️ Разработка новых типов ДОЛЖНА производиться с учетом сериализации.
Правильный выбор сериализации для поддержки
✔️ Если экземпляры типа необходимо сохранять или использовать в веб-службах, РЕКОМЕНДУЕТСЯ выбрать поддержку сериализации контракта данных.
✔️ Если требуется дополнительный контроль над XML-форматом, создаваемым при сериализации типа, РЕКОМЕНДУЕТСЯ выбрать поддержку XML-сериализации вместо сериализации контракта данных или в дополнение к ней.
Поддержка этой технологии может потребоваться в определенных сценариях взаимодействий, где необходимо использование конструкций XML, неподдерживаемых при сериализации контракта данных, например при создании XML-атрибута.
✔️ Если экземпляры типа должны передаваться за пределы границ архитектуры удаленного взаимодействия .NET, РЕКОМЕНДУЕТСЯ выбрать поддержку сериализации среды выполнения.
❌ НЕ рекомендуется выбирать сериализацию среды выполнения или XML-сериализацию для использования общих преимуществ, обеспечиваемых сохранением. Вместо этого рекомендуется использовать сериализацию контракта данных.
Поддержка сериализации контракта данных
Типы могут поддерживать сериализацию контракта данных при применении DataContractAttribute к типу и применении DataMemberAttribute к элементам (полям и свойствам) типа.
✔️ РЕКОМЕНДУЕТСЯ пометить элементы данных типа как открытые, если тип может быть использован в среде с частичным доверием.
В среде с полным доверием сериализаторы контрактов данных могут выполнять сериализацию и десериализацию закрытых типов и элементов, но в среде с частичным доверием эти операции могут выполняться только для открытых элементов.
✔️ НЕОБХОДИМО реализовать метод считывания и метод задания для всех свойств, имеющих DataMemberAttribute. При использовании сериализаторов контрактов данных тип считается сериализуемым только при наличии обоих методов - считывания и задания. (В платформа .NET Framework 3.5 с пакетом обновления 1 (SP1) некоторые свойства коллекции могут быть доступны только для получения.) Если тип не будет использоваться в частичном доверии, один или оба метода доступа к свойствам могут быть неопубликованы.
✔️ РЕКОМЕНДУЕТСЯ для инициализации десериализованных экземпляров использовать обратные вызовы сериализации.
При десериализации объектов конструкторы не вызываются. (В правиле существуют исключения. Конструкторы коллекций, помеченные как отмеченные, CollectionDataContractAttribute вызываются во время десериализации.) Поэтому любая логика, которая выполняется во время обычной сборки, должна быть реализована в качестве одного из обратных вызовов сериализации.
OnDeserializedAttribute
является наиболее часто используемым атрибутом обратного вызова. Другие атрибуты в семействе — OnDeserializingAttribute, OnSerializingAttribute и OnSerializedAttribute. Их можно использовать для пометки обратных вызовов, которые выполняются перед десериализацией, перед сериализацией и после сериализации соответственно.
✔️ РЕКОМЕНДУЕТСЯ использовать KnownTypeAttribute для указания конкретных типов, которые должны использоваться при десериализации более сложного графа объекта.
✔️ При создании и изменении сериализуемых типов РЕКОМЕНДУЕТСЯ обеспечивать прямую и обратную совместимость.
Необходимо помнить, что сериализуемые потоки будущих версий типа могут быть десериализованы в текущую версию типа и наоборот.
Необходимо учитывать, что элементы данных, даже закрытые и внутренние, не могут изменять свои имена, типы и даже свой порядок в будущих версиях типов, если не предприняты специальные меры для сохранения контракта с помощью явных параметров в его атрибутах.
При изменении сериализуемых типов проверьте совместимость сериализации. Попробуйте десериализовать новую версию в предыдущую и наоборот.
✔️ РЕКОМЕНДУЕТСЯ реализовать IExtensibleDataObject. Это даст возможность обеспечить цикл обработки значений между различными версиями типа.
Интерфейс дает сериализатору гарантию отсутствия потерь данных при выполнении циклов обработки значений. Свойство IExtensibleDataObject.ExtensionData используется для сохранения любых данных из будущих версий типа, неизвестных текущей версии. Таким образом оно не может сохранить их в элементах данных. Если текущая версия затем сериализуется и десериализуется в будущую, то дополнительные данные будут доступны в сериализованном потоке.
Поддержка XML-сериализации
Сериализация контрактов данных является основной (задаваемой по умолчанию) технологией сериализации в .NET Framework, однако существуют сценарии сериализации, которые эта технология не поддерживает. Например, она не обеспечивает полный контроль над формой XML-кода, создаваемого или используемого сериализатором. Если необходим столь высокий уровень контроля, используйте XML-сериализацию, разработав типы для поддержки этой технологии сериализации.
❌ Необходимо ИЗБЕГАТЬ разработки типов специально для XML-сериализации, за исключением случаев, когда необходим контроль над формой создаваемого XML-кода. Эта технология сериализации была заменена сериализацией контракта данных, описанной в предыдущем разделе.
✔️ РЕКОМЕНДУЕМ использовать реализацию интерфейса IXmlSerializable, если необходим более высокий уровень контроля над формой сериализуемого XML-кода, чем тот, который обеспечивается при применении атрибутов XML-сериализации. Два метода интерфейса, ReadXml и WriteXml, обеспечивают полный контроль над сериализуемым потоком XML. При этом обеспечивается возможность контроля над схемой XML, которая создается для типа путем применения XmlSchemaProviderAttribute
.
Поддержка сериализации во время выполнения
Сериализация во время выполнения представляет собой технологию, используемую при удаленном взаимодействии .NET. Если планируется передача типов с использованием удаленного взаимодействия .NET, то необходимо убедиться, что они поддерживают сериализацию во время выполнения.
Базовая поддержка сериализации во время выполнения может быть обеспечена с помощью SerializableAttribute. При более сложных сценариях выполняется реализация простого шаблона сериализации во время выполнения (реализация ISerializable и обеспечение конструктора сериализации).
✔️ РЕКОМЕНДУЕТСЯ обеспечить для типов поддержку сериализации во время выполнения, если типы будут использоваться при удаленном взаимодействии .NET. Например, в пространстве имен System.AddIn используется удаленное взаимодействие .NET и поэтому все типы, передаваемые между надстройками System.AddIn
, должны поддерживать сериализацию во время выполнения.
✔️ РЕКОМЕНДУЕТСЯ реализовать шаблон сериализации во время выполнения, если требуется полный контроль над процессом сериализации. Например, в том случае, когда необходимо преобразовать сериализуемые или десериализуемые данные.
Шаблон очень прост. Нужно всего лишь реализовать интерфейс ISerializable и предусмотреть специальный конструктор, который будет использоваться при десериализации объекта.
✔️ СДЕЛАЙТЕ конструктор сериализации защищенным и принимающим два параметра, типы и имена которых точно совпадают с показанными в этом образце.
[Serializable]
public class Person : ISerializable
{
protected Person(SerializationInfo info, StreamingContext context)
{
// ...
}
}
✔️ Элементы ISerializable НЕОБХОДИМО реализовать явно.
✔️ К реализации ISerializable.GetObjectData НЕОБХОДИМО применить запрос ссылки. Это гарантирует, что доступ к элементу имеют только полностью доверенный сериализатор и ядро.
Фрагменты: © Корпорация Майкрософт (Microsoft Corporation), 2005, 2009. Все права защищены.
Перепечатано с разрешения Pearson Education, Inc. из книги Инфраструктура программных проектов. Соглашения, идиомы и шаблоны для многократно используемых библиотек .NET (2-е издание), авторы: Кржиштоф Цвалина (Krzysztof Cwalina) и Брэд Абрамс (Brad Abrams). Книга опубликована 22 октября 2008 г. издательством Addison-Wesley Professional в рамках серии, посвященной разработке для Microsoft Windows.