Форум: "Основная";
Текущий архив: 2003.06.26;
Скачать: [xml.tar.bz2];
ВнизКак сохранить список Найти похожие ветки
← →
REA (2003-06-11 10:20) [0]Не могу вот вспомнить как сохранить список объектов компонента. Все объекты наследники TPersistent, но не одного типа - TCollection не подойдет. Если кто уже делал, подскажите как лучше. Сам список сейчас TObjectList не published property.
← →
Digitman (2003-06-11 10:53) [1]см.
TPersistent.DefineProperties()
TPersistent.DefineProperty()
TPersistent.DefineBinaryProperty()
TWriter.WriteListBegin/End
TReader.ReadListBegin/End
← →
REA (2003-06-11 11:20) [2]Да это я видел, но мысль голову не посетила - было бы проперти - нет проблем. Причем сам родительский объект TCollectionItem - и в список его объектов не запихать. Посмотреть что ли как в TComponent сделано?
← →
REA (2003-06-11 11:32) [3]Спасибо за подсказку с WriteList.
← →
Digitman (2003-06-11 11:41) [4]
> REA
> было бы проперти - нет проблем
на то и вышеприведенные методы, чтобы определить дополнительные (неопубликованные) св-ва, требуемые к сохранению/восстановлению наряду с автоматически сохраняемыми опубликованными св-вами
> список его объектов не запихать
это почему же ? см. 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.
← →
REA (2003-06-11 11:50) [5]Я имел ввиду, что 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. Тут такой фокус не пройдет.
← →
Digitman (2003-06-11 12:03) [6]
> CollectionItem не объект
как это "не объект" ? это же наследник TPersistent !
значит, при сохранении коллекции для каждого ее элемента будет австоматически вызван метод DefineProperties, который можно переопределить для каждого конкретного класса-наследника TCollectionItem.
И - далее : если экземпляр-наследник TCollectionItem хочет при сохранении его самого сохранить и свои собственные списки или поля (в кач-ве собственных св-в), то делает он это точно так же !
← →
REA (2003-06-11 12:13) [7]в смысле не компонет. ну не важно.
У меня не TCollectionItem нужно сохранять, с этим нет проблем, а проблемы с тем что он содержит, а он содержит список разнородных объектов наследников TPersistent (который кстати может расширяться за счет внешних Package plugin-ов). Метода WritePersistentObject нет, поэтому видимо придется наследовать все от TComponent и писать в список WriteComponent.
← →
Digitman (2003-06-11 12:23) [8]
> содержит список разнородных объектов наследников TPersistent
>
для каждого из них ты волен "вручную" вызвать DefineProperties() !
А у ж каждый из них сам запишет/прочитает свои индивидуальные св-ва
← →
REA (2003-06-11 12:28) [9]А как объекты то сами конструировать при чтении? Нужно же его класс знать. Опять же вручную это морока. Список классов заранее не известен. В TCollection класс определен (Он даже его не хранит видимо в ресурсе), а TComponent берет из списка зарегистрированных классов.
← →
Digitman (2003-06-11 12:50) [10]
> Нужно же его класс знать
при записи в поток записывай имя класса самым первым св-вом
> Опять же вручную это морока
Иных способов нет - тольуо "вручную", единожды определив поведение persistent-экз-ра при вызове его метода DefineProperties()
> Список классов заранее не известен
сделай так, чтобы он был известен
каждый из классов в списке зарегистрируй
иначе задача (в том виде как ты ее задумал) нерешаема
> TComponent берет из списка зарегистрированных классов
ничто не мешает класс зарегистрировать !
лишь бы существовала его декларация.
← →
REA (2003-06-11 13:02) [11]В общем для данного случая мне проще унаследовать не от TPersistent, а от TComponent. Он сам имя класса запишет. DefineProperties мне впрочем тоже понадобятся - сами эти классы в свою очередь содержат данные.
>ничто не мешает класс зарегистрировать !
Это обязательно.
Спасибо!
← →
Digitman (2003-06-11 13:26) [12]в целом - да
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;
в результате при сохранении/восстановлении некоего компонента автоматически будут сохранены/восстановлены все его "дети"
← →
REA (2003-06-11 14:30) [13]Я в курсе. Я так уже делал, но на этот раз структура получилась такая: Компонент - Документ (тоже компонент) - Документ с данными (наследник) - Данные Root (Collection) - Блоки данных (CollectionItems) - Поля данных (TComponent по видимому) - Собственно Данные. И все это безобразие нужно сохранять.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.06.26;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.029 c