![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Сохранение/загрузка Persistent'a в поток [D5]
jack128 © (2004-08-15 15:40:00)Есть иерархия объетов. Нужно что бы все объкты иерархии могли сохронять себя поток. Так как иерархия весь обширная (порядка 50 классов) , то писать методы SaveToStream/LoadFromStream для каждого класса несколько лениво, решил использовать RTTI. Сейчас это выглядит так:
typeНо у меня сильное впечатление, чтоо туплю. Задача, думаю достаточно распростронённая и, наверника есть какое нить стандартное решение. По крайней мере без переписывания TReader'a ??
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;
GuAV (2004-08-15 16:05:00) [21]Сейчас, когда сделал классом, ещё больше сходство ;-)
Да я понимаю то же самое, но
> компонент оверхед неплохой накатывает..
, а тут ничего лишнего только то что мне нужно.
jack128 (2004-08-15 16:02:00) [22]
> Я когда решил юзать RTTI напрямую TypInfo юзал
> вот тут вылаживал идею, правда сейчас уже всё переделал,
> интересно - выложу.
> http://www.delphimaster.ru/cgi-bin/forum.pl?id=1091963555&n=0
глянь в исходники ридера и райтера и увидишь приметно тоже самое ;-)
jack128 (2004-08-15 15:59:00) [23]э-э-э-э-э... Не хочется.. Объектов много, тысячи/десятки тысяч..А компонент оверхед неплохой накатывает..
GuAV (2004-08-15 15:59:00) [24]
> решил использовать RTTI
Я когда решил юзать RTTI напрямую TypInfo юзал
вот тут вылаживал идею, правда сейчас уже всё переделал, интересно - выложу.
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1091963555&n=0
GuAV (2004-08-15 15:52:00) [25]Юзай наследника TComponent.
Если считаешь, что TComponent - это VCL, то TPersistent - это тоже VCL.