Wenn es mit etwas Umwegen gehen darf, wäre eine TList-Ableitung möglich.
Diese würde den ItemTypen bekommen und könnte damit sofort loslegen. (die Felder einer Klasse sind nichts weiter als ein Record
)
Hier erstmal das FileOfClass-Dingsbums...
Delphi-Quellcode:
unit uFileOfClass;
interface
uses
Classes,
Contnrs;
type
TFileOfClass =
class(TObjectList)
private
fItemType: TClass;
protected
procedure WriteItemToStream(
const aItem: TObject; aStream: TStream);
virtual;
function ReadItemFromStream(aStream: TStream): TObject;
virtual;
public
property ItemType: TClass
read fItemType;
procedure SaveToStream(aStream: TStream);
virtual;
procedure LoadFromStream(aStream: TStream);
virtual;
procedure SaveToFile(
const aFileName:
string);
virtual;
procedure LoadFromFile(
const aFileName:
string);
virtual;
constructor Create(aItemType: TClass; aOwnsObjects: Boolean = True);
virtual;
end;
implementation
uses
SysUtils;
{ TFileOfClass }
constructor TFileOfClass.Create(aItemType: TClass; aOwnsObjects: Boolean);
begin
inherited Create(aOwnsObjects);
fItemType := aItemType;
end;
procedure TFileOfClass.LoadFromFile(
const aFileName:
string);
var
Stream : TStream;
begin
Stream := TFileStream.Create(aFileName, fmOpenRead);
try
LoadFromStream(Stream);
finally
Stream.Free();
end;
end;
procedure TFileOfClass.LoadFromStream(aStream: TStream);
begin
while aStream.Position < aStream.Size
do
Add(ReadItemFromStream(aStream));
end;
function TFileOfClass.ReadItemFromStream(aStream: TStream): TObject;
begin
Result := ItemType.NewInstance();
aStream.
Read(Pointer(Result)^, ItemType.InstanceSize - SizeOf(Pointer));
end;
procedure TFileOfClass.SaveToFile(
const aFileName:
string);
var
Stream : TStream;
begin
Stream := TFileStream.Create(aFileName, fmCreate);
try
SaveToStream(Stream);
finally
Stream.Free();
end;
end;
procedure TFileOfClass.SaveToStream(aStream: TStream);
var
i : Integer;
begin
for i := 0
to Count - 1
do
begin
WriteItemToStream(Items[i], aStream);
end;
end;
procedure TFileOfClass.WriteItemToStream(
const aItem: TObject; aStream: TStream);
begin
aStream.
Write(Pointer(aItem)^, ItemType.InstanceSize - SizeOf(Pointer));
end;
end.
Ist nicht schön.... aber was kann in Verbindung mit typisierten Dateien schon schön sein.
Dein "record" sähe wohl so aus.
Delphi-Quellcode:
type
TBlubbClass = class
private
fLfdNr: Integer;
fKdNr: Integer;
fName: myShortString;
fVorname: myShortString;
published
property LfdNr: Integer read fLfdNr write fLfdNr;
property KdNr: Integer read fKdNr write fKdNr;
property Name: myShortString read fName write fName;
property Vorname: myShortString read fVorname write fVorname;
end;
Reinschreiben könntest du es so:
Delphi-Quellcode:
var
myList : TFileOfClass;
Blubb : TBlubbClass;
begin
myList := TFileOfClass.Create(TBlubbClass);
try
Blubb := TBlubbClass.Create();
Blubb.LfdNr := 1;
Blubb.KdNr := 10;
Blubb.Name := 'Schulz';
Blubb.Vorname := 'Hans';
myList.Add(Blubb);
Blubb := TBlubbClass.Create();
Blubb.LfdNr := 2;
Blubb.KdNr := 20;
Blubb.Name := 'Müller';
Blubb.Vorname := 'Bert';
myList.Add(Blubb);
myList.SaveToFile('Miep.txt');
finally
myList.Free();
end;
end;
Auslesen wäre so möglich:
Delphi-Quellcode:
var
myList : TFileOfClass;
i : Integer;
begin
myList := TFileOfClass.Create(TBlubbClass);
try
myList.LoadFromFile('Miep.txt');
for i := 0 to myList.Count - 1 do
with TBlubbClass(myList[i]) do
ListBox1.Items.Add(Name + ', ' + Vorname);
finally
myList.Free();
end;
end;
Dumm ist nur, dass es eigentlich totaler Blödsinn ist.
Ändere den "record" zu einer Ableitung von TCollectionItem und schon kannst du auch strings und alles andere benutzen.
Anstatt der TFileOfClass würde die
dpCollection ins Spiel kommen.
Bist du auf Kompatibilität zu ekligen typisierten Dateien angewiesen musst du wohl den Weg oben gehen (und hoffen, dass der Compiler die Felder nicht irgendwann intern verdreht).
Bist du es nicht sehe ich keine Ausrede weiterhin typisierte Dateien zu nehmen.
Delphi-Quellcode:
type
TBlubbClass = class(TCollectionItem)
private
fLfdNr: Integer;
fKdNr: Integer;
fName: string;
fVorname: string;
published
property LfdNr: Integer read fLfdNr write fLfdNr;
property KdNr: Integer read fKdNr write fKdNr;
property Name: string read fName write fName;
property Vorname: string read fVorname write fVorname;
end;