Читать «ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание» онлайн - страница 398

Эндрю Троелсен

Рис. 17.1 Простой объектный граф

При чтении объектных графов дли соединяющих стрелок вы можете использовать выражения "зависит от" и "ссылается на". Поэтому на рис. 17.1 вы можете видеть, что класс Car ссылается на класс Radio (в силу отношения локализации, "has-a"), а класс JamesBondCar ссылается на Car (в силу отношения подчиненности, "is-а") и на Radio (в силу того, что соответствующий защищенный член-переменная данным классом наследуется).

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

[Car 3, ref 2], [Radio 2], [JamesBondCar 1, ref 3, ref 2]

Проанализировав эту формулу, вы снова увидите, что объект 3 (Car) имеет зависимость в отношения объекта 2 (Radio). Объект 2 (Radio) является "индивидуалистом", которому никто не требуется. Наконец, объект 1 (JamesBondCar) имеет зависимость в отношении как объекта 3, так и объекта 2. В любом случае, когда выполняется сериализация или реконструкция экземпляра JamesBondCar, объектный граф дает гарантию того, что типы Radio и Car тоже будут участвовать в процессе.

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

Конфигурирование объектов для сериализации

Чтобы сделать объект доступным сервису сериализации .NET, достаточно пометить каждый связанный класс атрибутом [Serializable]. И это все (правда!). Если вы решите, что некоторые члены данного класса не должны (или, возможно, не могут) участвовать в процессе сериализации, обозначьте соответствующие поля атрибутом [NonSerialized]. Это может быть полезно тогда, когда в классе, предназначенном для сериализации, есть члены-переменные, которые запоминать не нужно (например, фиксированные или случайные значения, динамические данные и т.п.), и вы хотите уменьшить размеры сохраняемого графа.

Для начала вот вам класс Radio, обозначенный атрибутом [Serializable], за исключением одной переменной (radioID), которая помечена атрибутом [NonSerialized], и поэтому не будет сохраняться в указанном потоке данных.

[Serializable]

public class Radio {

 public bool hasTweeters;

 public bool hasSubWoofers;

 public double[] stationPresets;

 [NonSerialized]

 public string radioID = "XF-552RR6";

}

Класс JamesBondCar и базовый класс Car, также обозначенные атрибутом [Serializable], определяют следующие поля данных.

[Serializable]

public class Car {

 public Radio theRadio = new Radio();

 public bool isHatchBack;

}

[Serializable]

public class JamesBondCar: Car {

 public bool canFly;

 public bool canSubmerge;

}

Следует знать о том, что атрибут [Serializable] не наследуется. Таким образом, если вы получаете класс из типа, обозначенного атрибутом [Serializable], дочерний класс тоже следует обозначить атрибутом [Serializable], иначе он при сериализации сохраняться не будет. На самом деле все объекты в объектном графе должны обозначаться атрибутом [Serializable]. При попытке с помощью BinaryFormatter или SoapFormatter выполнить сериализацию объекта. не подлежащего сериализации, в среде выполнения генерируется исключение SerializationException.