Шрифт:
Проанализировав эту формулу, вы снова увидите, что объект 3 (Car) имеет зависимость в отношения объекта 2 (Radio). Объект 2 (Radio) является "индивидуалистом", которому никто не требуется. Наконец, объект 1 (JamesBondCar) имеет зависимость в отношении как объекта 3, так и объекта 2. В любом случае, когда выполняется сериализация или реконструкция экземпляра JamesBondCar, объектный граф дает гарантию того, что типы Radio и Car тоже будут участвовать в процессе.
Приятной особенностью процесса сериализации является то, что граф, изображающий взаимосвязи ваших объектов, создается в фоновом режиме и автоматически. Позже, в этой же главе, вы убедитесь, что при желании вы все же можете участвовать в построении такого объектного графа.
Конфигурирование объектов для сериализации
Чтобы сделать объект доступным сервису сериализации .NET, достаточно пометить каждый связанный класс атрибутом [Serializable]. И это все (правда!). Если вы решите, что некоторые члены данного класса не должны (или, возможно, не могут) участвовать в процессе сериализации, обозначьте соответствующие поля атрибутом [NonSerialized]. Это может быть полезно тогда, когда в классе, предназначенном для сериализации, есть члены-переменные, которые запоминать не нужно (например, фиксированные или случайные значения, динамические данные и т.п.), и вы хотите уменьшить размеры сохраняемого графа.
Для начала вот вам класс Radio, обозначенный атрибутом [Serializable], за исключением одной переменной (radioID), которая помечена атрибутом [NonSerialized], и поэтому не будет сохраняться в указанном потоке данных.
Класс JamesBondCar и базовый класс Car, также обозначенные атрибутом [Serializable], определяют следующие поля данных.
Следует знать о том, что атрибут [Serializable] не наследуется. Таким образом, если вы получаете класс из типа, обозначенного атрибутом [Serializable], дочерний класс тоже следует обозначить атрибутом [Serializable], иначе он при сериализации сохраняться не будет. На самом деле все объекты в объектном графе должны обозначаться атрибутом [Serializable]. При попытке с помощью BinaryFormatter или SoapFormatter выполнить сериализацию объекта. не подлежащего сериализации, в среде выполнения генерируется исключение SerializationException.
Открытые поля, приватные поля и открытые свойства
Заметим, что в указанных выше классах поля данных были определены открытыми только для того, чтобы упростить пример. Конечно, с точки зрения объектно-ориентированного подхода предпочтительнее использовать приватные данные, доступные через открытые свойства. Также для простоты не было определено никаких пользовательских конструкторов для этих типов, поэтому все их поля данных, не получившие начальных значений, получат значения, предусмотренные по умолчанию.
"Отодвинув" принципы объектно-ориентированного программирования в сторону, вы можете спросить, какие именно определения полей данных ожидают "видеть" различные средства форматирования, при отправке этих данных в поток. Ответ здесь зависит от многого. Если вы сохраняете объект с помощью BinaryFormatter, то определения не имеют абсолютно никакого значений. Этот тип предназначен дан сохранения всех предназначенных для сериализации полей типа, независимо от того, являются ли они общими полями, приватными полями или приватными полями, доступными через свойства типа. Однако ситуация оказывается совершенно иной, если вы используете тип XmlSerializer или тип SoapFormatter. Эти типы выполняют сериализацию только открытых полей данных и приватных данных, доступных через открытые свойства.
Напомним, однако, что если имеются поля данных, которые вы не хотите сохранять в объектном графе, вы можете селективно использовать для них атрибут [NonSerialized], как это сделано со строковым полем типа Radio.
Выбор формата сериализации
После конфигурации типов для участия в схеме сериализации .NET следующим шагом является выбор формата, который должен использоваться при сохранении объектного графа. В .NET 2.0 вы имеете на выбор три варианта.