Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.08.29;
Скачать: CL | DM;

Вниз

Сохранение/загрузка Persistent a в поток   Найти похожие ветки 

 
jack128 ©   (2004-08-15 15:40) [0]

Есть иерархия объетов. Нужно что бы все объкты иерархии могли сохронять себя поток. Так как иерархия весь обширная (порядка 50 классов) , то писать методы SaveToStream/LoadFromStream для каждого класса несколько лениво, решил использовать RTTI.  Сейчас это выглядит так:

type
 TReaderCrack = class(TReader)
 public
   procedure DefineProperty(const Name: string;
     ReadData: TReaderProc; WriteData: TWriterProc;
     HasData: Boolean); override;
   procedure DefineBinaryProperty(const Name: string;
     ReadData, WriteData: TStreamProc;
     HasData: Boolean); override;
 end;
 TWriterCrack = class(TWriter);
 TPersistentCrack = class(TPersistent);

procedure SavePersistent(Stream: TStream; Instance: TPersistent);
var
 PropList: PPropList;
 PropCount: Integer;
 Writer: TWriterCrack;
 i: Integer;
begin
 Assert(Assigned(Instance), "Object must be not nil");
 PropCount := GetTypeData(Instance.ClassInfo).PropCount;
 GetMem(PropList, SizeOf(PPropInfo) * PropCount);
 try
   PropCount := GetPropList(Instance.ClassInfo, tkProperties - [tkClass], PropList);
   if PropCount = 0 then exit;
   Writer := TWriterCrack.Create(Stream, 1024);
   try
     Writer.WriteListBegin;
     for i := 0 to PropCount - 1 do
       if IsStoredProp(Instance, PropList[i]) then
         Writer.WriteProperty(Instance, PropList[i]);
     Writer.WriteListEnd;
     TPersistentCrack(Instance).DefineProperties(Writer);
   finally
     Writer.Free;
   end;
 finally
   FreeMem(PropList);
 end;
end;

procedure LoadPersistent(Stream: TStream; Instance: TPersistent);
var
 Reader: TReaderCrack;
begin
 Assert(Assigned(Instance), "Object must be not nil");
 Reader := TReaderCrack.Create(Stream, 1024);
 try
   Reader.ReadListBegin;
   while not Reader.EndOfList do
     Reader.ReadProperty(Instance);
   Reader.ReadListEnd;
   TPersistentCrack(Instance).DefineProperties(Reader);
 finally
   Reader.Free;
 end;
end;

{ TReaderCrack }

procedure TReaderCrack.DefineBinaryProperty(const Name: string; ReadData,
 WriteData: TStreamProc; HasData: Boolean);
var
 Count: LongInt;
 ms: TMemoryStream;
begin
 if not (Assigned(ReadData) and HasData) then Exit;
 CheckValue(vaBinary);
 ms := TMemoryStream.Create;
 try
   Read(Count, SizeOf(Count));
   ms.Size := Count;
   Read(ms.Memory^, Count);
   ReadData(ms);
 finally
   ms.Free;
 end;
end;

procedure TReaderCrack.DefineProperty(const Name: string;
 ReadData: TReaderProc; WriteData: TWriterProc; HasData: Boolean);
var
 SavePos: Integer;
begin
 if not (Assigned(ReadData) and HasData) then Exit;
 SavePos := Position;
 if not SameText(Name, ReadStr) then
 begin
   Position := SavePos;
   Exit;
 end;
 ReadData(Self);
end;
Но у меня сильное впечатление, чтоо туплю. Задача, думаю достаточно распростронённая и, наверника есть какое нить стандартное решение. По крайней мере без переписывания TReader"a ??


 
GuAV ©   (2004-08-15 15:52) [1]

Юзай наследника TComponent.
Если считаешь, что TComponent - это VCL, то TPersistent - это тоже VCL.


 
GuAV ©   (2004-08-15 15:59) [2]


> решил использовать RTTI

Я когда решил юзать RTTI напрямую TypInfo юзал
вот тут вылаживал идею, правда сейчас уже всё переделал, интересно - выложу.
http://delphimaster.net/view/1-1091963555/


 
jack128 ©   (2004-08-15 15:59) [3]

э-э-э-э-э... Не хочется.. Объектов много, тысячи/десятки тысяч..А компонент оверхед неплохой накатывает..


 
jack128 ©   (2004-08-15 16:02) [4]


> Я когда решил юзать RTTI напрямую TypInfo юзал
> вот тут вылаживал идею, правда сейчас уже всё переделал,
> интересно - выложу.
> http://delphimaster.net/view/1-1091963555/

глянь в исходники ридера и райтера и увидишь приметно тоже самое ;-)


 
GuAV ©   (2004-08-15 16:05) [5]

Сейчас, когда сделал классом, ещё больше сходство ;-)
Да я понимаю то же самое, но
> компонент оверхед неплохой накатывает..
, а тут ничего лишнего только то что мне нужно.


 
jack128 ©   (2004-08-15 16:25) [6]


> а тут ничего лишнего только то что мне нужно.
ну я процедуру загрузки не собираюсь оптимизировать. Все таки эти объекты весятв памяти постоянно, сохраняет все это пользователь от силы раз в полчаса..
Но что мне не нравиться, так это то что я переписал TReader! Это меня несколько беспокоит..И вообще велосипед избретает - все это было уже..


 
GuAV ©   (2004-08-15 16:33) [7]


> это то что я переписал TReader

А зачем это понадобилось?
Особо с этими не разбирался, но
constructor Create(Stream: TStream; BufSize: Integer);


 
jack128 ©   (2004-08-15 16:39) [8]


> А зачем это понадобилось?
конкретно вот из-за этого

procedure TReader.DefineProperty(const Name: string;
 ReadData: TReaderProc; WriteData: TWriterProc; HasData: Boolean);
begin
 if SameText(Name, FPropName) and Assigned(ReadData) then
 begin
   ReadData(Self);
   FPropName := "";
 end;
end;

когда в своей процедуре я вызываю Instance.DefineProperties(Reader), FPropName у нас равно "", со всеми втекающими и вытекающими последствиями..


 
GuAV ©   (2004-08-15 17:16) [9]

FPropName читается в
procedure TReader.ReadProperty(AInstance: TPersistent);


 
jack128 ©   (2004-08-15 17:38) [10]

это понятно, но TRaeder.ReadProperty читает Published свойства, а а мне то нужно прочитать те свойства, которые были определены в TPersistent.DefineProperties!!!


 
GuAV ©   (2004-08-15 20:22) [11]

TComponent.DefineProperties
пишет Left и Top - этот способ тоже не устраивает?


 
jack128 ©   (2004-08-15 20:31) [12]

и что? Ты не умничай, ты пальцем покажи ;-) Как конкретно мне записать/прочитать Persistent в поток. Ну переопределил я DefineProperties и что дальше?


 
GuAV ©   (2004-08-15 20:38) [13]


> Ты не умничай, ты пальцем покажи ;-)

Я не умничаю - я не умнее тебя.
Я показал:
procedure TComponent.DefineProperties(Filer: TFiler);
var
 Ancestor: TComponent;
 Info: Longint;
begin
 Info := 0;
 Ancestor := TComponent(Filer.Ancestor);
 if Ancestor <> nil then Info := Ancestor.FDesignInfo;
 Filer.DefineProperty("Left", ReadLeft, WriteLeft,
   LongRec(FDesignInfo).Lo <> LongRec(Info).Lo);
 Filer.DefineProperty("Top", ReadTop, WriteTop,
   LongRec(FDesignInfo).Hi <> LongRec(Info).Hi);
end;

и так не работает? Или не устраивает?
зы я там сделал свои IniReader/IniWriter, потому что считаю, что проще самому сделать, чем разбираться.


 
jack128 ©   (2004-08-15 21:04) [14]

ты не понял. что я от тебя хотел.
Короче выяснил в чем у мя затык был. Моя ошибка была в том, что я считал

> TRaeder.ReadProperty читает Published свойства,
нет, этот метод так же читает и свойства определенные через TPersistint.DefineProperies. Почему то сразу я до этого не дошёл.. Соответственно код упрочается безобразия:

type
 TReaderCrack = class(TReader);
 TWriterCrack = class(TWriter);
 TPersistentCrack = class(TPersistent);

procedure SavePersistent(Stream: TStream; Instance: TPersistent);
var
 PropList: PPropList;
 PropCount: Integer;
 Writer: TWriterCrack;
 i: Integer;
begin
 Assert(Assigned(Instance), "Object must be not nil");
 PropCount := GetTypeData(Instance.ClassInfo).PropCount;
 GetMem(PropList, SizeOf(PPropInfo) * PropCount);
 try
   PropCount := GetPropList(Instance.ClassInfo, tkProperties - [tkClass], PropList);
   Writer := TWriterCrack.Create(Stream, 1024);
   try
     Writer.WriteListBegin;
     for i := 0 to PropCount - 1 do
       if IsStoredProp(Instance, PropList[i]) then
         Writer.WriteProperty(Instance, PropList[i]);
     TPersistentCrack(Instance).DefineProperties(Writer);
     Writer.WriteListEnd;
   finally
     Writer.Free;
   end;
 finally
   FreeMem(PropList);
 end;
end;

procedure LoadPersistent(Stream: TStream; Instance: TPersistent);
var
 Reader: TReaderCrack;
begin
 Assert(Assigned(Instance), "Object must be not nil");
 Reader := TReaderCrack.Create(Stream, 1024);
 try
   Reader.ReadListBegin;
   while not Reader.EndOfList do
     Reader.ReadProperty(Instance);
   Reader.ReadListEnd;
 finally
   Reader.Free;
 end;
end;


 
jack128 ©   (2004-08-15 21:07) [15]


> потому что считаю, что проще самому сделать, чем разбираться
гм.. Возможно ты и прав, но как там у тя в анкете написано?
Ctrl+Click - ещё интереснее, вот мне и интересно ;-)


 
GuAV ©   (2004-08-15 21:28) [16]


> Ctrl+Click - ещё интереснее, вот мне и интересно ;-)

Я думал те всегда грустно и неитересно ;-)
с твоего (надеюсь) разрешение - самое интересное - Ctrl+C + Ctrl+V :-)


 
GuAV ©   (2004-08-15 21:40) [17]

Кажется, БАГ!

GetMem(PropList, SizeOf(PPropInfo) * PropCount); - убрать из твоего кода

Ctrl+Click ;-)

function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): Integer;
begin
 Result := GetTypeData(TypeInfo)^.PropCount;
 if Result > 0 then
 begin
   GetMem(PropList, Result * SizeOf(Pointer));
   GetPropInfos(TypeInfo, PropList);
 end;
end;


 
GuAV ©   (2004-08-15 21:47) [18]

Это из Д7, если в Д5 аналогично, то имхо так:

Assert(Assigned(Instance), "Object must be not nil");
PropCount := GetPropList(Instance.ClassInfo, tkProperties - [tkClass], PropList);
try
  Writer := TWriterCrack.Create(Stream, 1024);


 
jack128 ©   (2004-08-15 22:03) [19]

не-а, не баг
function GetPropList(TypeInfo: PTypeInfo; TypeKinds: TTypeKinds;
 PropList: PPropList): Integer;


 
GuAV ©   (2004-08-15 22:15) [20]

В Д7 не так... может лучше GetPropInfos, чтоб было портируемо в Д7 ?


 
GuAV ©   (2004-08-15 22:25) [21]


> function GetPropList(TypeInfo: PTypeInfo; TypeKinds: TTypeKinds;
>  PropList: PPropList): Integer;

Такой в Д7 нет. Так что мы на разных языках говорим :-(
(Такая есть.
function GetPropList(TypeInfo: PTypeInfo; TypeKinds: TTypeKinds;
 PropList: PPropList; SortList: Boolean): Integer;)


 
jack128 ©   (2004-08-15 22:32) [22]

Да ну.. Если б эта функция, только здесь использовалась бы, то можно было бы.. А так.. Учитывая, что на семёрку я переходить не собираюсь..  Если когда нить это произойдёт, компилятор сам подскажет об ошибке..

Ну вобщем ты понял - мне ЛЕНЬ!!! ;-) :-))

ЗЫ Вообще говоря если используешь модуль TypInfo - то всегда будь готов к несовместимости версий. Хотя конкретно в данном случаи я вообще не понимаю логику борланда - нафиг так делоть было..

<off>
 если таки соберешся писать в Borland по поводу конструкторов и если/когда получишь ответ - свистнешь, ОКи?
</off>


 
jack128 ©   (2004-08-15 22:38) [23]


> Так что мы на разных языках говорим
именно. Ты на Delphi7, а я на Delphi5


 
GuAV ©   (2004-08-15 22:52) [24]


> Ну вобщем ты понял - мне ЛЕНЬ!!! ;-) :-))

Ладно, себе я сам переведу под свой вкус.

> модуль TypInfo

Ты на нём ещё F1 нажми, смотри как "много" в справке про него - три ф-ции, самые ненужные.


>  если таки соберешся писать в Borland по поводу конструкторов
> и если/когда получишь ответ - свистнешь, ОКи?

Мне лень повторяить твои эксперименты, давай всё что есть с тогдашних на мыло, а я уже спрошу.

А веточку - то в потрепаться пора...


 
GuAV ©   (2004-08-16 01:15) [25]

Получил письмо, спасибо.



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

Текущий архив: 2004.08.29;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.032 c
14-1092207521
Григорьев Антон
2004-08-11 10:58
2004.08.29
Клавиатура для настоящих патриотов :))


9-1084221010
Werwolf
2004-05-11 00:30
2004.08.29
Ворпос на засыпку....


14-1092322796
YurikGL
2004-08-12 18:59
2004.08.29
Стадии заболевания компьютерным вирусом.


4-1089551383
DeMoN_Astra
2004-07-11 17:09
2004.08.29
Диалап соединение


4-1090156748
banderas
2004-07-18 17:19
2004.08.29
Как скопировать свой собственный exe