Example of how to store a Component and its properties
to a disk file or a Blob field

author : 
        Theodoros Bebekis
        Thessaloniki, Greece
        e-mail: bebekis@mail.otenet.gr

----------------------------------------------------------------------
Lets suppose that we have a complex data type 
For example:


 TThirdLayer = record
   .
   .
 end;


 TSecondLayer = record
   .
   .
   ThirdLayer :TThirdLayer;
 end; 


 TFirstLayer = record
   .
   .
   SecondLayer :TSecondLayer;
 end;  

 
 Jobs : array [0..9] of TFirstLayer;


And we want to save Jobs in a file for later use.


I tried many approaches to solve this problem.
I finally tried to make it a Component to benefit
from Delphi's Component  streaming capabilities
and defore starting struggling with DefineProperty,
DefineBinaryProperty, ReadData, WriteData etc., 
I posted a message to Borland's NewsGroups
and then Rick Rogers from TeamB pointed to me 
the right direction.


My question:

=========================================================

I have a component with some properties like records and array of
records. Can I store it to a disk file including its properties
and all the data they hold?
And how can I read it back from disk?


Here is an example of my component:

//====================== unit Jobs ==========================
unit Jobs;

interface


uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
 
type 
  
  TJobType = (jtNormal, jtSpecial, jtFull, jtEmpty);
  TMyEnum  = (meOne, meTwo, meThree, meFour, meFive);

  TJobLabel = record
    JobName,
    Job_ID      : string;
    JobType     : TJobType;
  end;

  TThirdLayer = record
    S      : string;
    I      : integer;
    B      : boolean;
    F      : double;
  end;
 
  TSecondLayer = record    
    aRect      : TRect;
    aSet       : set of TMyEnum;
    ThirdLayer : TThirdLayer;    
  end;
 
  TJob = record                   // First Layer
    Index       : integer;
    Name        : string;
    Full        : boolean;
    SecondLayer : TSecondLayer;
  end;

type
  TJobHolder = class(TComponent)
  private  
//================================================================
    FJobLabel   : TJobLabel;
    FJobArray   : array [0..9] of TJob;

    function  GetJobArray(Index:integer):TJob;
    procedure SetJobArray(Index:integer; Value:TJob);
  public   
//================================================================
    
  published
//===============================================================
    property JobLabel:TJobLabel read FJobLabel write FJobLabel;
    property JobArray[Index:integer]:TJob  read GetJobArray write
SetJobArray;  

  end;
 
implementation

{-------------------------GetJobArray------------------------------------}
function  TJobHolder.GetJobArray(Index:integer):TJob;
begin
    Result:=FJobArray[Index];
end;  { GetJobArray }

{----------------------------SetJobArray--------------------------------}
procedure TJobHolder.SetJobArray(Index:integer; Value:TJob);
begin
   FJobArray[Index]:=Value;
end; { SetJobArray }


end.

//====================== EOF unit Jobs ==========================


TIA


-- 

===================================================
Theodoros Bebekis
Thessaloniki,  Greece
bebekis@mail.otenet.gr



=====================================================

Rick's reply:

=====================================================

On 18 Jun 1998 14:13:38 GMT, "Theodoros Bebekis"
<bebekis@mail.otenet.gr> wrote:

> Can I store it to a disk file including its properties
> and all the data they hold?

Two ways. First, use ReadComponentResFile and WriteComponentResFile.
This takes advantage of Delphi's automatic and powerful component
streaming system.

However, to use component streams, you'll need to change your class
structure in a number of ways. That's because only certain published
properties (not including records) are automatically written to the
stream (because RTTI isn't generated for records).

Here are the changes: 1) you'll need to change TJobLabel,
TSecondLayer, and TThirdLayer to descend from TPersistent; 2) you'll
need publish all properties in TJobLabel, TSecondLayer, and
TThirdLayer which you want persistent; and 3) you'll need to change
TJobRecord to descend from TCollectionItem, FJobArray to TCollection,
and publish the JobArray collection property.

Alternatively, you could simply write a LoadFromStream and
SaveToStream method for TJobHolder. Of course, this means you'll need
to implement file i/o (such FileStream.ReadBuffer) logic to read and
write the file format you design.

-- 
Rick Rogers (TeamB) | Fenestra Technologies
http://www.fenestra.com/

=======================================================


I found a relevant example in VCL - DBGrid.Columns - and finally
I made TJobHolder class to work.


I have also made some routines in case somebody needs to save
a component like this to BlobField, using TBlobStream.

Thats all.

Copy all files in the same directory, compile and run

PS. Sorry for uncommented code but I think its easy
    to understand what is going on if you study it

Theodoros