Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Компоненты";
Текущий архив: 2006.02.12;
Скачать: [xml.tar.bz2];

Вниз

Сохранение поля типа TObjectList   Найти похожие ветки 

 
Andrushk   (2005-08-17 15:07) [0]

Господа, подскажите плиз как написать сохранение поля типа TObjectList компонента.

Нашел подобный вопрос: http://delphimaster.net/view/5-1123089950/
-но здесь посоветовали воспользоваться TColection.

Первый раз возникает необходимость сохранить сложное свойство, не соображу как правильнее и оптимальней воспользоваться Filer.DefineBinaryProperty/Filer.DefineProperty.

TObjectList ссылается на объекты типа:

 TFilterOneField = class
   FName: string;
   FType: integer;
   isUse: boolean;
   VisibleFName: string;
   DataSetField: string;
   QueryNames: string;
   ReferenceForm: TForm;
   ReferenceFieldName: string;
   ...
 end;


 
Юрий Зотов ©   (2005-08-17 20:13) [1]

Вам принципиально важно, чтобы это был именно TObjectList? Если да, то что-то вроде этого (в работе не проверял, только компилировал!):

unit YzSavedObjectList;

interface

uses
 Classes, Contnrs, Forms;

type
 TYzSavedObject = class
 private
   procedure ReadSelf(Reader: TReader);
   procedure WriteSelf(Writer: TWriter);
 public
   Str: string;
   Int: integer;
   Form: TForm;
 end;

 TYzSavedObjectListContainer = class(TComponent)
 private
   FList: TObjectList;
   procedure ReadList(Reader: TReader);
   procedure WriteList(Writer: TWriter);
 protected
   procedure DefineProperties(Filer: TFiler); override;
 public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
   property List: TObjectList read FList;
 end;

implementation

{ TYzSavedObject }

procedure TYzSavedObject.ReadSelf(Reader: TReader);
begin
 with Reader do
 begin
   ReadListBegin;
   Str := ReadString;
   Int := ReadInteger;
   if ReadBoolean then
     Form := ReadRootComponent(nil) as TForm
   else
     Form := nil;
   ReadListEnd
 end
end;

procedure TYzSavedObject.WriteSelf(Writer: TWriter);
begin
 with Writer do
 begin
   WriteListBegin;
   WriteString(Str);
   WriteInteger(Int);
   if Assigned(Form) then
   begin
     WriteBoolean(True);
     WriteRootComponent(Form)
   end
   else
     WriteBoolean(False);
   WriteListEnd
 end;
end;

{ TYzSavedObjectListContainer }

constructor TYzSavedObjectListContainer.Create(AOwner: TComponent);
begin
 inherited;
 FList := TObjectList.Create
end;

procedure TYzSavedObjectListContainer.DefineProperties(Filer: TFiler);

 function IsListSaved: boolean;
 begin
   Result := (Filer.Ancestor = nil) and (FList.Count > 0)
 end;

begin
 inherited;
 Filer.DefineProperty("YzSavedObjects", ReadList, WriteList, IsListSaved)
end;

destructor TYzSavedObjectListContainer.Destroy;
begin
 FList.Free;
 inherited
end;

procedure TYzSavedObjectListContainer.ReadList(Reader: TReader);
begin
 Reader.ReadListBegin;
 FList.Clear;
 while not Reader.EndOfList do
   TYzSavedObject(FList.Items[FList.Add(TYzSavedObject.Create)]).ReadSelf(Reader);
 Reader.ReadListEnd
end;

procedure TYzSavedObjectListContainer.WriteList(Writer: TWriter);
var
 i: integer;
begin
 Writer.WriteListBegin;
 for i := 0 to FList.Count - 1 do
   TYzSavedObject(FList.Items[i]).WriteSelf(Writer);
 Writer.WriteListEnd
end;

end.

А если принципиальной разницы нет, то будет гораздо проще наследовать TFilterOneField от TCollectionItem, а вместо TObjectList использовать TOwnedCollection. Дело в том, что для коллекций TReader и TWriter имеют уже готовые ReadCollection и WriteCollection, а если коллекцию вынести в published, то и вообще ничего не потребуется, все будет сохраняться и читаться автоматически (к тому же, Вы сможете редактировать элементы коллекции прямо в Object Inspector).


 
Andrushk   (2005-08-18 11:36) [2]

Большое спасибо, в очередной раз убеждаюсь что все гениальное просто:-)

Открыл для себя, что в DefineProperty имя параметра не может совпадать с именем свойства...возможно я баклан и это всем известный факт :-). У меня вчера с этим проблемы были - компонет сохраняется, а на загрузку непонятные ошибки лезут. И сегодня тоже самое было, пока не стал сравнивать чем мой код от Вашего отличается.

Вобщем спасибо!


 
Юрий Зотов ©   (2005-08-18 14:28) [3]

> Andrushk   (18.08.05 11:36) [2]

> DefineProperty имя параметра не может совпадать с именем
> свойства

Точно так. Может совпадать, но совершенно не обязано. Даже более того - этот параметр ни к каким свойствам вообще не имеет никакого отношения. DefineProperties просто определяет способ сохранения и загрузки некоего параметра с произвольным именм, которое хранится в DFM. А уж что это за параметр, где и как он используется - среде все это глубоко по барабану (например, TComponent свои Left и Top упаковывает и хранит в DesignInfo).

> ...возможно я баклан

Судя по этой ветке - вряд ли...
:о)

> и это всем известный факт

Далеко не всем. Но грамотные разработчики компонентов знать об этом все же должны.

> У меня вчера с этим проблемы были - компонет сохраняется, а
> на загрузку непонятные ошибки лезут. И сегодня тоже самое
> было, пока не стал сравнивать

Если published-свойство хранится через DefineProperties, то в самом объявлении свойства обычно указывают stored False - чтобы избежать повторного сохранения. Судя по описанной проблеме, не исключено, что Вам стоит поступить так же.


 
Andrushk   (2005-08-18 15:19) [4]

Странно, но stored False не помогло...
Как только имя published-свойства совпадает с именем параметра в DefineProperties при загрузке параметров компонента возникает ошибка...а сохраняется нормально.


 
Юрий Зотов ©   (2005-08-18 17:41) [5]

> Странно, но stored False не помогло...

Похоже, просто остался старый DFM, где свойство было уже раньше записано. Пакету сделайте Build (не Compile), а DFM подчистите Блокнотом.


 
Наиль ©   (2005-08-18 21:21) [6]

А зачем блокнотом? Есть же Alt+F12.
Лучше почистить, а потом Build.


 
Наиль ©   (2005-08-18 21:28) [7]

>[1]
Большое спасибо за DefineProperties. В своё время, была в нём необходимость, удалось обойтись без него. Но стандартные методы всегда лучше.


 
Юрий Зотов ©   (2005-08-18 21:29) [8]

> Наиль ©   (18.08.05 21:21) [6]

Если чистить DFM в среде с еще неперебилденным пакетом, то не исключено, что при переходе просмотра обратно в форму среда все запишет в DFM снова.


 
Andrushk   (2005-08-19 09:38) [9]

Либо у меня руки не от туда растут либо что-то не так:-))

 published
   ...
   property FilterFields: TFilterFields read FFieldsList write FFieldsList stored false;
   ...
 inherited DefineProperties(Filer);
 Filer.DefineProperty("FilterFields",ReadList,WriteList,IsListSaved);
   ...

нормально сохраняется, смотрел dfm-ку, но читаться не хочет, а стоит написать "FiltFields" - все становиться нормально, даже прямо в dfm-ке подправляешь и она нормально грузится...

может stored только на сохранение действует?
из хелпа:
If a property has no stored directive, it is treated as if stored True were specified.
...
...and the stored specifier is True, then the property"s value is saved. Otherwise, the property"s value is not saved.

а про чтение ничего не сказано, только запись.


 
Наиль ©   (2005-08-19 22:19) [10]

Написал длиное-длиное сообщение о том, что как и почему. И всё потерялось при не удачной передаче сообщения в форум. Поэтому в двух словах:
Проанализируй строчки, 6371-6372, 6385-6393 в модуле Classes. Особено обрати внимание на if PropInfo <> nil . Если добъешься, что GetPropInfo для заданого свойства возвращает nil, то получишь то, что хотел.
Для того, чтобы этого добиться проанализируй строчки от 887 в модуле TypInfo. Напомню переход на нужную строчку Alt+G. Для перехода в модуль Classes пишешь Classes и нажимаешь Ctrl+Enter.
Удачи.


 
Andrushk   (2005-08-22 09:13) [11]

> Наиль ©   (19.08.05 22:19) [10]

Спасибо, попробую.



Страницы: 1 вся ветка

Форум: "Компоненты";
Текущий архив: 2006.02.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.04 c
15-1137944178
Kerk
2006-01-22 18:36
2006.02.12
650летие Самары


15-1137869558
Джо
2006-01-21 21:52
2006.02.12
Два файла с одинаковыми именами в одной папке


2-1138130238
Бася
2006-01-24 22:17
2006.02.12
Какая прога лучше для создания файла помощи?


4-1133526336
Kerk
2005-12-02 15:25
2006.02.12
Выбор ADO-провайдера


15-1138178660
-Nick-
2006-01-25 11:44
2006.02.12
Закрытие периода





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский