Как сохранить значение свойства в потокDelphi , Компоненты и Классы , RTTIКак сохранить значение свойства в поток
Автор: Rick Rogers How can I save properties of a TList to a stream? I need the entire list to be saved as a whole and not as individual objects. A TList doesn't have any intrinsic streaming capability built into it, but it is very easy to stream anything that you want with a little elbow grease. Think about it: a stream is data. Classes have properties, whose values are data. It isn't too hard to write property data to a stream. Here's a simple example to get you going. This is but just one of many possible approaches to saving object property data to a stream: unit uStreamableExample; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Contnrs; type TStreamableObject = class(TPersistent) protected function ReadString(Stream: TStream): string; function ReadLongInt(Stream: TStream): LongInt; function ReadDateTime(Stream: TStream): TDateTime; function ReadCurrency(Stream: TStream): Currency; function ReadClassName(Stream: TStream): ShortString; procedure WriteString(Stream: TStream; const Value: string); procedure WriteLongInt(Stream: TStream; const Value: LongInt); procedure WriteDateTime(Stream: TStream; const Value: TDateTime); procedure WriteCurrency(Stream: TStream; const Value: Currency); procedure WriteClassName(Stream: TStream; const Value: ShortString); public constructor CreateFromStream(Stream: TStream); procedure LoadFromStream(Stream: TStream); virtual; abstract; procedure SaveToStream(Stream: TStream); virtual; abstract; end; TStreamableObjectClass = class of TStreamableObject; TPerson = class(TStreamableObject) private FName: string; FBirthDate: TDateTime; public constructor Create(const AName: string; ABirthDate: TDateTime); procedure LoadFromStream(Stream: TStream); override; procedure SaveToStream(Stream: TStream); override; property Name: string read FName write FName; property BirthDate: TDateTime read FBirthDate write FBirthDate; end; TCompany = class(TStreamableObject) private FName: string; FRevenues: Currency; FEmployeeCount: LongInt; public constructor Create(const AName: string; ARevenues: Currency; AEmployeeCount: LongInt); procedure LoadFromStream(Stream: TStream); override; procedure SaveToStream(Stream: TStream); override; property Name: string read FName write FName; property Revenues: Currency read FRevenues write FRevenues; property EmployeeCount: LongInt read FEmployeeCount write FEmployeeCount; end; TStreamableList = class(TStreamableObject) private FItems: TObjectList; function Get_Count: LongInt; function Get_Objects(Index: LongInt): TStreamableObject; public constructor Create; destructor Destroy; override; function FindClass(const AClassName: string): TStreamableObjectClass; procedure Add(Item: TStreamableObject); procedure Delete(Index: LongInt); procedure Clear; procedure LoadFromStream(Stream: TStream); override; procedure SaveToStream(Stream: TStream); override; property Objects[Index: LongInt]: TStreamableObject read Get_Objects; default; property Count: LongInt read Get_Count; end; TForm1 = class(TForm) SaveButton: TButton; LoadButton: TButton; procedure SaveButtonClick(Sender: TObject); procedure LoadButtonClick(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public Path: string; end; var Form1: TForm1; implementation {$R *.DFM} resourcestring DEFAULT_FILENAME = 'test.dat'; procedure TForm1.SaveButtonClick(Sender: TObject); var List: TStreamableList; Stream: TStream; begin List := TStreamableList.Create; try List.Add(TPerson.Create('Rick Rogers', StrToDate('05/20/68'))); List.Add(TCompany.Create('Fenestra', 1000000, 7)); Stream := TFileStream.Create(Path + DEFAULT_FILENAME, fmCreate); try List.SaveToStream(Stream); finally Stream.Free; end; finally List.Free; end; end; { TPerson } constructor TPerson.Create(const AName: string; ABirthDate: TDateTime); begin inherited Create; FName := AName; FBirthDate := ABirthDate; end; procedure TPerson.LoadFromStream(Stream: TStream); begin FName := ReadString(Stream); FBirthDate := ReadDateTime(Stream); end; procedure TPerson.SaveToStream(Stream: TStream); begin WriteString(Stream, FName); WriteDateTime(Stream, FBirthDate); end; { TStreamableList } procedure TStreamableList.Add(Item: TStreamableObject); begin FItems.Add(Item); end; procedure TStreamableList.Clear; begin FItems.Clear; end; constructor TStreamableList.Create; begin FItems := TObjectList.Create; end; procedure TStreamableList.Delete(Index: LongInt); begin FItems.Delete(Index); end; destructor TStreamableList.Destroy; begin FItems.Free; inherited; end; function TStreamableList.FindClass(const AClassName: string): TStreamableObjectClass; begin Result := TStreamableObjectClass(Classes.FindClass(AClassName)); end; function TStreamableList.Get_Count: LongInt; begin Result := FItems.Count; end; function TStreamableList.Get_Objects(Index: LongInt): TStreamableObject; begin Result := FItems[Index] as TStreamableObject; end; procedure TStreamableList.LoadFromStream(Stream: TStream); var StreamCount: LongInt; I: Integer; S: string; ClassRef: TStreamableObjectClass; begin StreamCount := ReadLongInt(Stream); for I := 0 to StreamCount - 1 do begin S := ReadClassName(Stream); ClassRef := FindClass(S); Add(ClassRef.CreateFromStream(Stream)); end; end; procedure TStreamableList.SaveToStream(Stream: TStream); var I: Integer; begin WriteLongInt(Stream, Count); for I := 0 to Count - 1 do begin WriteClassName(Stream, Objects[I].ClassName); Objects[I].SaveToStream(Stream); end; end; { TStreamableObject } constructor TStreamableObject.CreateFromStream(Stream: TStream); begin inherited Create; LoadFromStream(Stream); end; function TStreamableObject.ReadClassName(Stream: TStream): ShortString; begin Result := ReadString(Stream); end; function TStreamableObject.ReadCurrency(Stream: TStream): Currency; begin Stream.Read(Result, SizeOf(Currency)); end; function TStreamableObject.ReadDateTime(Stream: TStream): TDateTime; begin Stream.Read(Result, SizeOf(TDateTime)); end; function TStreamableObject.ReadLongInt(Stream: TStream): LongInt; begin Stream.Read(Result, SizeOf(LongInt)); end; function TStreamableObject.ReadString(Stream: TStream): string; var L: LongInt; begin L := ReadLongInt(Stream); SetLength(Result, L); Stream.Read(Result[1], L); end; procedure TStreamableObject.WriteClassName(Stream: TStream; const Value: ShortString); begin WriteString(Stream, Value); end; procedure TStreamableObject.WriteCurrency(Stream: TStream; const Value: Currency); begin Stream.Write(Value, SizeOf(Currency)); end; procedure TStreamableObject.WriteDateTime(Stream: TStream; const Value: TDateTime); begin Stream.Write(Value, SizeOf(TDateTime)); end; procedure TStreamableObject.WriteLongInt(Stream: TStream; const Value: LongInt); begin Stream.Write(Value, SizeOf(LongInt)); end; procedure TStreamableObject.WriteString(Stream: TStream; const Value: string); var L: LongInt; begin L := Length(Value); WriteLongInt(Stream, L); Stream.Write(Value[1], L); end; { TCompany } constructor TCompany.Create(const AName: string; ARevenues: Currency; AEmployeeCount: Integer); begin FName := AName; FRevenues := ARevenues; FEmployeeCount := AEmployeeCount; end; procedure TCompany.LoadFromStream(Stream: TStream); begin FName := ReadString(Stream); FRevenues := ReadCurrency(Stream); FEmployeeCount := ReadLongInt(Stream); end; procedure TCompany.SaveToStream(Stream: TStream); begin WriteString(Stream, FName); WriteCurrency(Stream, FRevenues); WriteLongInt(Stream, FEmployeeCount); end; procedure TForm1.LoadButtonClick(Sender: TObject); var List: TStreamableList; Stream: TStream; Instance: TStreamableObject; I: Integer; begin Stream := TFileStream.Create(Path + DEFAULT_FILENAME, fmOpenRead); try List := TStreamableList.Create; try List.LoadFromStream(Stream); for I := 0 to List.Count - 1 do begin Instance := List[I]; if Instance is TPerson then ShowMessage(TPerson(Instance).Name); if Instance is TCompany then ShowMessage(TCompany(Instance).Name); end; finally List.Free; end; finally Stream.Free; end; end; procedure TForm1.FormCreate(Sender: TObject); begin Path := ExtractFilePath(Application.ExeName); end; initialization RegisterClasses([TPerson, TCompany]); end. Как сохранить значение свойства в поток: с помощью класса TStreamableObject и его наследников можно сохранять значения свойств объектов в потоке, используя методы ReadString, ReadLongInt, ReadDateTime, WriteString, WriteLongInt, WriteDateTime. Комментарии и вопросыМатериалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |