е. будут сохранены его read/write published- и псевдосвойства.

Примером published-свойства типа коллекции является свойство Columns класса TListView. Вот как может выглядеть фрагмент сериализованной коллекции:

object ListView1: TListView . . . Columns = < item Caption = 'Column 1' ImageIndex = 2 MinWidth = 10 end item . . . end item . . . end> . . . end

Итак, если есть необходимость в связи «один-ко-многим», мы поступаем следующим образом: создаём свою коллекцию, делаем композицию этой коллекции с нужным классом и выносим её в published-свойство. А что, если нужна связь «многие-ко-многим?» Или «многие-к-одному» – если понадобится, скажем, сериализовать систему из трёх объектов, A, B и C, и при этом как A, так и B должны иметь ссылки на C? Другие компоненты

Классический пример подобной системы – система Action’ов на форме. Один и тот же Action, несущий в своих свойствах информацию о себе, может быть назначен одновременно нескольким control-ам на форме (например, кнопке и пункту меню). В подобных ситуациях объект, на который могут ссылаться один, несколько или ни одного объекта, должен быть компонентом.

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

object Form1: TForm1 . . . object Button1: TButton . . . Action = Action1 end object Button2: TButton . . . Action = Action2 end object ActionList1: TActionList . . . object Action1: TAction Caption = 'Action1' end object Action2: TAction Caption = 'Action2' end end end

Вот где нам пригодилась уникальность значений свойства Name! Вспомним, что владельцем всех этих Button’ов и Action’ов является Form1. Уникальность имён в пределах общего владельца позволяет системе сериализации использовать их в качестве идентификаторов. После загрузки происходит полное восстановление ссылок по именам, и мы вновь получаем систему объектов с перекрёстными ссылками.

Есть одна тонкость, которую надо учитывать, используя этот сериализуемый тип. Корректное восстановление ссылок на основании имён произойдёт лишь если корневой объект является общим владельцем для компонентов, которые содержат ссылки, и компонентов, на которые они ссылаются. Именно из-за этого выше упоминалось о том, что на практике используется лишь самый простой вариант иерархии владения: корневой компонент владеет всем, что входит в сериализацию, остальные компоненты не владеют ничем. Механизм десериализации устроен таким образом, что вне зависимости от того, как было раньше, после загрузки из потока корневой компонент окажется владельцем всех других компонентов.

Ну и конечно, ещё в программе надо позаботиться о том, чтобы все сериализуемые компоненты имели непустые уникальные имена. Об ответственности за сериализацию

Не пугайтесь названия этого раздела. Речь пойдёт всего лишь о том, как сделать так, чтобы компонент записывал вместе с собой в поток другие.

Было бы ошибкой предполагать, что компонент сериализует то, чем он владеет. Владение и ответственность за сериализацию – это разные отношения, и по умолчанию компонент не сериализует вместе с собой ничего. Впрочем, в VCL есть два класса-наследника TComponent, которые сериализуют именно то, чем владеют: это TForm и TDataModule, и если посмотреть их исходный код, можно увидеть, что в них переопределён protected-метод TComponent.GetChildren.

procedure GetChildren(Proc: TGetChildProc; Root: TComponent); dynamic;

где

type TGetChildProc = procedure (Child: TComponent) of object;

GetChildren – переопределяемый метод, в классе TComponent он пуст. Он автоматически вызывается в тот момент, когда система сериализации хочет опросить компонент о том, какие ещё компоненты нужно сохранять.

<<< 0 1 2 3 4 5 6 7 8 >>>
Хостинг от uCoz