Шрифт:
Предположим, например, что вы создали приложение с графическим интерфейсом и хотите обеспечить конечным пользователям возможность сохранить информацию об их предпочтениях. Для этого вы можете определить класс (например, с именем UserPrefs), инкапсулирующий, скажем, 20 полей данных. Если использовать тип System.IO.BinaryWriter, вам придется вручную сохранять каждое поле объекта UserPrefs. А когда вы захотите загрузить данные из соответствующего файла обратно в память, вам придется использовать System.IO.BinaryReader и (снова вручную) прочитать каждое значение, чтобы сконфигурировать новый объект UserPrefs.
Это, конечно, выполнимо, но вы можете сэкономить себе немало времени, просто указав для класса UserPrefs атрибут [Serializable]. В этом случае для сохранения полного состояния объекта достаточно будет нескольких строк программного кода.
Сохранять объекты с помощью средств сериализации .NET очень просто, но процессы, происходящие при этом в фоновом режиме, оказываются весьма сложными. Например, когда объект сохраняется в потоке, все соответствующие данные (базовые классы, вложенные объекты и т.п.) автоматически сохраняются тоже. Таким образом, при попытке выполнить сериализацию производного класса в этом процессе будет задействована вся цепочка наследования.
Как вы сможете убедиться позже, множество взаимосвязанных объектов можно представить в виде объектного графа. Сервис сериализации .NET позволяет сохранить и объектный граф, причем в самых разных форматах. В предыдущем примере программного кода использовался тип BinaryFormatter, поэтому состояние объекта UserPrefs сохранялось в компактном двоичном формате. Если использовать другие типы, то объектный граф можно сохранить в формате SOAP (Simple Object Access Protocol – простой протокол доступа к объектам) или в формате XML. Эти форматы могут быть полезны тогда, когда необходимо гарантировать, что ваши сохраненные объекты легко перенесут "путешествие" через операционные системы, языки и архитектуры.
Наконец, следует понимать, что объектный граф можно сохранить в любом производном от System.IO.Stream типе. В предыдущем примере объект UserPrefs сохранялся в локальном файле с помощью типа FileStream. Но если бы требовалось сохранить объект в памяти, следовало бы использовать тип MemoryStream. Это необходимо для того, чтобы последовательность данных корректно представляла состояния объектов соответствующего графа.
Роль объектных графов
Как уже упоминалось, при сериализации объекта среда CLR учитывает состояния всех связанных объектов. Множество связанных объектов представляется объектным графом. Объектные графы обеспечивают простой способ учета взаимных связей в множестве объектов, и не обязательно, чтобы эти связи в точности проецировались в классические связи объектно-ориентированного программирования (такие как отношения старшинства, и подчиненности), хотя они моделируют эту парадигму достаточно хорошо.
Каждому объекту в объектном графе назначается уникальное числовое значение. Следует иметь в виду, что эти числовые значения, приписываемые членам в объектном графе, произвольны и не имеют никакого смысла вне графа. После назначения всем объектам числового значения объектный граф может начать запись множества зависимостей каждого объекта.
Для примера предположим, что вы создали множество классов, моделирующих типы автомобилей (а что же еще?). Вы имеете базовый класс, названный Car (автомобиль), который "имеет" Radio (радио). Другой класс, JamesBondCar (автомобиль Джеймса Бонда), расширяет базовый тип Car. На рис. 17.1 показан возможный объектный граф, моделирующий указанные взаимосвязи.
Рис. 17.1 Простой объектный граф
При чтении объектных графов дли соединяющих стрелок вы можете использовать выражения "зависит от" и "ссылается на". Поэтому на рис. 17.1 вы можете видеть, что класс Car ссылается на класс Radio (в силу отношения локализации, "has-a"), а класс JamesBondCar ссылается на Car (в силу отношения подчиненности, "is-а") и на Radio (в силу того, что соответствующий защищенный член-переменная данным классом наследуется).
Конечно, для представления графа связанных объектов среда CLR картины в памяти не рисует. Вместо этого взаимосвязи, указанные в диаграмме, представляются математической формулой, которая выглядит примерно так.