Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-84234
Совсем новичок
2003-06-08 16:25
2003.06.26
Как сделать паузу или подождать прорисовывания TLabel?


1-84187
Юнгман
2003-06-11 14:54
2003.06.26
ComboBox


1-84219
DJ Vano
2003-06-13 01:04
2003.06.26
TMemo


1-84339
ghg
2003-06-16 09:57
2003.06.26
проблема с параметром-массивом в процедуре


14-84570
Shaman
2003-06-04 10:50
2003.06.26
Runtime error 105 - что значит?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский