Thema: Delphi Dynamisches Record?

Einzelnen Beitrag anzeigen

Robert_G
(Gast)

n/a Beiträge
 
#4

Re: Dynamisches Record?

  Alt 22. Mai 2005, 17:17
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 dpCollectiondpCollection 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;
  Mit Zitat antworten Zitat