Поделиться через


Сериализация

Замечание

Это содержимое перепечатывается разрешением Pearson Education, Inc. из руководства по проектированию платформы: соглашения, идиомы и шаблоны для повторно используемых библиотек .NET, 2-го выпуска. Этот выпуск был опубликован в 2008 году, и книга с тех пор была полностью пересмотрена в третьем выпуске. Некоторые сведения на этой странице могут быть устаревшими.

Сериализация — это процесс преобразования объекта в формат, который можно легко сохранить или транспортировать. Например, можно сериализовать объект, передать его через Интернет с помощью HTTP и десериализировать его на целевом компьютере.

Платформа .NET Framework предлагает три основных технологии сериализации, оптимизированные для различных сценариев сериализации. В следующей таблице перечислены эти технологии и основные типы платформ, связанные с этими технологиями.

Имя технологии Основные типы Сценарии
Сериализация данных контракта DataContractAttribute
DataMemberAttribute
DataContractSerializer
NetDataContractSerializer
DataContractJsonSerializer
ISerializable
Общая сохраняемость
Веб-службы
JSON (JavaScript Object Notation)
Сериализация 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 Remoting. Если вы считаете, что типы будут передаваться с помощью .NET Remoting, необходимо убедиться, что они поддерживают сериализацию времени выполнения.

Базовая поддержка сериализации среды выполнения может быть предоставлена путем применения SerializableAttribute, а более сложные сценарии могут включать реализацию простого шаблона сериализации среды выполнения (реализация ISerializable и предоставление конструктора сериализации).

✔️ Рассмотрите возможность поддержки сериализации времени выполнения, если ваши типы будут использоваться для удаленного взаимодействия .NET. Например, пространство имен System.AddIn использует .NET Remoting, поэтому все типы, обменяемые между System.AddIn надстройками, должны поддерживать сериализацию среды выполнения.

✔️ Подумайте о реализации шаблона сериализации среды выполнения, если требуется полный контроль над процессом сериализации. Например, если требуется преобразовать данные по мере сериализации или десериализации.

Шаблон очень прост. Все, что необходимо сделать, заключается в реализации ISerializable интерфейса и предоставлении специального конструктора, который используется при десериализации объекта.

✔️ Сделайте конструктор сериализации защищённым и укажите два параметра, типы и имена которых точно соответствуют показанным в примере.

[Serializable]
public class Person : ISerializable
{
    protected Person(SerializationInfo info, StreamingContext context)
    {
        // ...
    }
}

✔️ Следует явно реализовать ISerializable члены.

✔️ Примените требование ссылки к реализации ISerializable.GetObjectData. Это гарантирует, что только полностью доверенное ядро и сериализатор времени выполнения имеют доступ к члену.

© Часть 2005, 2009 Корпорация Майкрософт. Все права защищены.

Перепечатан с разрешения Pearson Education, Inc. из Руководство по проектированию: Соглашения, идиомы и шаблоны для повторного использования библиотек .NET, 2-е издание Кшиштоф Чвалина и Брэд Абрамс, опубликованное 22 октября 2008 года Addison-Wesley Профессиональный в рамках серии разработки Microsoft Windows.

См. также