Як зберегти список

Як зберегти список

Не можу ось згадати як зберегти список об'єктів компонента. Всі об'єкти спадкоємці TPersistent, але не одного типу - TCollection не підійде. Якщо хто вже робив, підкажіть як краще. Сам список зараз TObjectList НЕ published property.

см.
TPersistent.DefineProperties ()
TPersistent.DefineProperty ()
TPersistent.DefineBinaryProperty ()
TWriter.WriteListBegin / End
TReader.ReadListBegin / End

Так це я бачив, але думка голову не відвідала - було б проперти - немає проблем. Причому сам батьківський об'єкт TCollectionItem - і в список його об'єктів не запхати. Подивитися чи як в TComponent зроблено?

Дякую за підказку з WriteList.


> Було б проперти - немає проблем


> Список його об'єктів не запхати

це чому ж. см. TReader.ReadCollection, TWriter.WriteCollection

ReadCollection is a helper method used by other reader methods to read a tagged collection value at the current reader Position. ReadCollection iterates through items in a collection so that each item in a collection property has an opportunity to stream out its properties. This method does not write out the number of items and the collection indices, because a user can add or delete items.

Я мав на увазі, що CollectionItem не об'єкт і у нього немає властивості Objects. Зараз як раз дивлюся:
procedure TWriter.WriteCollection (Value: TCollection);
var
I: Integer;
OldAncestor: TPersistent;
begin
OldAncestor: = Ancestor;
Ancestor: = nil;
try
WriteValue (vaCollection);
if Value <> nil then
for I: = 0 to Value.Count - 1 do
begin
WriteListBegin;
WriteProperties (Value.Items [I]);
WriteListEnd;
end;
WriteListEnd;
finally
Ancestor: = OldAncestor;
end;
end;
Там механізм трохи інший - у мене об'єкти різних класів. Він же при завантаженні робить Add і потім ReadProperties. Тут такий фокус не пройде.


> CollectionItem не об'єкт

як це "не об'єкт". це ж спадкоємець TPersistent.

значить, при збереженні колекції для кожного її елемента буде австоматіческі викликаний метод DefineProperties, який можна перевизначити для кожного конкретного класу-спадкоємця TCollectionItem.

І далі. якщо екземпляр-спадкоємець TCollectionItem хоче при збереженні його самого зберегти і свої власні списки або поля (в кач-ве власних св-в), то робить він це точно так же!

в сенсі не компонет. Ну не важливо.
У мене не TCollectionItem потрібно зберігати, з цим немає проблем, а проблеми з тим що він містить, а він містить список різнорідних об'єктів спадкоємців TPersistent (який до речі може розширюватися за рахунок зовнішніх Package plugin-ів). Методу WritePersistentObject немає, тому мабуть доведеться наслідувати все від TComponent і писати в список WriteComponent.


> Містить список різнорідних об'єктів спадкоємців TPersistent
>

для кожного з них ти вільний "вручну" викликати DefineProperties ().
А у ж кожен з них сам запише / прочитає свої індивідуальні св-ва

А як об'єкти то самі конструювати при читанні? Треба ж його клас знати. Знову ж вручну це морока. Список класів заздалегідь не відомий. У TCollection клас визначений (Він навіть його не зберігає мабуть в ресурсі), а TComponent бере зі списку зареєстрованих класів.


> Потрібно ж його клас знати

при записі в потік записуй ім'я класу найпершим св-вом


> Знову ж вручну це морока

Інших способів немає - тольуо "вручну", одного разу визначивши поведінку persistent-прим-ра при виклику його методу DefineProperties ()


> Список класів заздалегідь не відомий

зроби так, щоб він був відомий
кожен з класів в списку зареєструй
інакше завдання (в тому вигляді як ти її задумав) не вирішується


> TComponent бере зі списку зареєстрованих класів

ніщо не заважає клас зареєструвати.
аби існувала його декларація.

Загалом для даного випадку мені простіше успадкувати немає від TPersistent, а від TComponent. Він сам ім'я класу запише. DefineProperties мені втім теж знадобляться - самі ці класи в свою чергу містять дані.

> Ніщо не заважає клас зареєструвати.
Це обов'язково.

в цілому - так
TComponent як спадкоємець дещо полегшить рутинну роботу
Але реєстрація, звичайно, необхідна, тільки вже не класу, а компонента (TRegisterComponent [s])

придивися ще до TComponent.GetChildren ()
в кач-ве досить розумної альтернативи можна відмовитися від використання колекцій на користь св-ва списку TComponent.Components [] - знову ж зменшення рутинної роботи. Раз TComponent вже реалізує список (і управління ним) компонентів, для яких він є власником, гріх ним не скористатися)

TMyObject = class (TComponent)
.
protected
procedure GetChildren (Proc: TGetChildProc); override;
.
end;
.
procedure TMyObject.GetChildren (Proc: TGetChildProc);
var
i: Integer;
begin
for i: = 0 to ComponentCount - 1 do
Proc (Components [i]);
end;

в результаті при збереженні / відновленні якогось компонента автоматично будуть збережені / відновлені всі його "діти"

Я в курсі. Я так вже робив, але на цей раз структура вийшла така: Компонент - Документ (теж компонент) - Документ з даними (спадкоємець) - Дані Root (Collection) - Блоки даних (CollectionItems) - Поля даних (TComponent по видимому) - Власне Дані . І все це неподобство потрібно зберігати.

Пам'ять: 0.75 MB
Час: 0.061 c