Hallo,
ich habe mal ein kleines Beispiel gebastelt.
Hier die
unit für das 2-dimensionale Array:
Delphi-Quellcode:
unit TwoD_Array;
interface
uses classes, dpcollection;
Type
TDimension_2 =
class(TCollectionItem)
private
FText:
String;
public
procedure Assign(Source : TPersistent);
override;
published
property Text:
String read FText
write FText;
end;
TDimension_1 =
class(TCollectionItem)
private
FD2Collection : TJsCollection;
FName:
String;
public
constructor Create(Collection: TCollection);
override;
destructor Destroy;
override;
procedure Assign(Source : TPersistent);
override;
published
property Name :
String read FName
write FName;
property D2 : TJsCollection
read FD2Collection
write FD2Collection;
// Dies ist die 2. Dimension !!!
end;
implementation
{ TDimension_1 }
procedure TDimension_1.Assign(Source: TPersistent);
{Wenn Assign nicht überschrieben wird, werden die eigenen Eigenschaft
bei einem Aufruf von Assign auch mit erfasst}
begin
If Source
is TDimension_1
then
begin
FName:=TDimension_1(Source).
Name;
FD2Collection.Assign(TDimension_1(Source).D2);
end
else
inherited Assign(Source);
end;
constructor TDimension_1.Create(Collection: TCollection);
begin
inherited Create(Collection);
FD2Collection:=TJsCollection.Create(TDimension_2);
end;
destructor TDimension_1.Destroy;
begin
FD2Collection.Free;
inherited Destroy;;
end;
{ TDimension_2 }
procedure TDimension_2.Assign(Source: TPersistent);
begin
If Source
is TDimension_2
then
begin
FText:=TDimension_2(Source).Text;
end
else
inherited Assign(Source);
end;
end.
Das ist grundsätzlich alles !!!!!!!!!
TDimension_1 ist die 1. Dimension des "Arrays". Dieses Objekt kann hier lediglich einen Namen aufnehmen. Das wäre vergleichbar mit
sArray : TArray of String;
Jetzt hat TDimension_1 die Eigenschaft D2. Das ist die 2. Dimension. Über D2 können dem Element (Objekt) aus TDimension_1 beliebig viele Strings (Eigenschaft Text von TDimension_2) zugeordnet werden.
Jetzt kommt der Source des Beispiels. Ich habe alle Codezeilen, die nichts mit der Anwendung
von dbCollection zutun haben weggelassen.
Delphi-Quellcode:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, TwoD_Array, dpcollection, StdCtrls, XPMan;
type
TForm1 =
class(TForm)
...
private
{ Private-Deklarationen }
FApplicationPath :
String;
FCollection : TJsCollection;
FD1_Item : TDimension_1;
...
public
{ Public-Deklarationen }
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FCollection:=TJsCollection.Create(TDimension_1);
//X
...
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FCollection.Free;
//X
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// erzeuge ein Element (Objekt) in der 1. Ebene
FD1_Item:=FCollection.Add
as TDimension_1;
//X
FD1_Item.
Name:=edtName.Text;
//X
end;
procedure TForm1.btnTextClick(Sender: TObject);
var
D2_Item : TDimension_2;
begin
// Hier wird jetzt die 2. Dimension gefüllt
If FD1_Item<>
Nil then
begin
D2_Item:=FD1_Item.D2.Add
as TDimension_2;
//X
D2_Item.Text:=edtText.Text;
//X
end;
end;
procedure TForm1.btnSaveClick(Sender: TObject);
begin
FCollection.SaveToFile(FApplicationPath+'
Testdatei.clc');
//X
// Die Endung .clc ist hier natürlich völlig willkürlich gewählt
end;
procedure TForm1.btnLoadClick(Sender: TObject);
begin
FCollection.LoadFromFile(FApplicationPath+'
Testdatei.clc');
//X
end;
end.
Wie hier zu erkennen ist reicht ein simples LoadFromFile / SaveToFile aus,
um das "Array" zu speichern oder zu laden.
Aber jetzt kommt der eigenliche Hammer !!!
Nehmen wir einmal an, Du möchtest zu jedem Element (Objekt) der 1. Dimension in der
2. Dimension beliebig viele Bitmaps speichern !!! MIt der dpCollection ist das überhaupt
kein Problem. Ich werde jetzt die Klasse TDimension_2 so erweitern das auch Bitmaps
gespeichert werden können. D.h. das Speichern und Laden geschieht dann völlig automatisch!
Delphi-Quellcode:
TDimension_2 = class(TCollectionItem)
private
FText: String;
FBitmap: TBitmap;
procedure SetBitmap(const Value: TBitmap);
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
procedure Assign(Source : TPersistent); override;
published
property Bitmap : TBitmap read FBitmap write SetBitmap;
property Text: String read FText write FText;
end;
...
constructor TDimension_2.Create(Collection: TCollection);
begin
inherited Create(Collection);
FBitmap:=TBitmap.Create;
end;
destructor TDimension_2.Destroy;
begin
FBitmap.Free;
inherited Destroy;
end;
procedure TDimension_2.Assign(Source: TPersistent);
begin
If Source is TDimension_2 then
begin
FBitmap.Assign(TDimension_2(Source).Bitmap);
FText:=TDimension_2(Source).Text;
end
else
inherited Assign(Source);
end;
procedure TDimension_2.SetBitmap(const Value: TBitmap);
begin
FBitmap.Assign(Value);
end;
Das ist alles !!!
So lassen sich alle Nachfahren von TPersistent speichern
Jetzt kommt der 2. Hammer!!!
Durch die Einführung der Bitmap wurde das Dateiformat geändert.
Mit einer typisierten Datei hätte man das Problem, dass das neue Programm
die alten Dateien nicht ohne weiteres lesen kann. Nicht so mit der dpCollection.
Die dpCollection verwendet das Delphi-Streamingsystem (das ist das Ding, das dafür sorgt,
das die Formulare mit all den Komponenten und Einstellungen die Ihr gemacht habt
in der
dfm-Datei landen). D.h. es werden nur die Eigenschaften aus der Datei gelesen,
die auch in der Datei enthalten sind. Die Eigenschaften, die nicht in der Datei sind
erhalten den Standardwert.
D.h. mit der dpCollection seit Ihr automatisch Abwärtskompatibel.