AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Library: Object-Pascal / Delphi-Language Delphi TObjectList mit polimorphen Objectstrukturen speichern
Thema durchsuchen
Ansicht
Themen-Optionen

TObjectList mit polimorphen Objectstrukturen speichern

Ein Thema von Taladan · begonnen am 18. Jun 2005
Antwort Antwort
Benutzerbild von Taladan
Taladan

Registriert seit: 5. Aug 2003
Ort: Osnabrück
505 Beiträge
 
Delphi 2005 Professional
 
#1

TObjectList mit polimorphen Objectstrukturen speichern

  Alt 18. Jun 2005, 18:34
Eine Objectliste kann man nich so leicht Speichern. Jedoch sollte dieser Ansatz euch eine doch recht einfache Lösung zeigen.
Beschreibung:
Unit: Daten
Zweck: Erstellen einer speicherbaren Objectliste mit polymorphen Objecten

Beschreibung:

TMyObjectList
Von einer TObjectlist wird eine neue Klasse Namens TMyObjectList abgeleitet.
Diese erhält weitere Routinen. Diese lauten SafeToStream, LoadToStream,
SaveToFile und LoadToFile.
Die function Add und die Eigenschaft Items werden Überschreiben, da die
Objectliste sich nicht auf eine Klasse speicherbarer Objecte fest legen soll.
Ebenfalls wird der Constructor überschrieben. Die Eigenschaft Items ist eine
ReadOnly-Eigenschaft. Da es sich bei Items um ein Array handelt, muß eine
Funktion die Rückgabe des Wertes übernehmen.
Die polimorphen Objecte werden während der Laufzeit zum Auslesen noche einmal
Registriert durch die procedure RegisterObeject (In diesen Beispiel nur eines).

TBaseObject:
Eine Ableitung von TPersistent. Nur so kann das Object nach den Auslesen neu
bestimmt (RegisterClass) und gesucht (FindClass) werden. Dieses Object hat die
proceduren LoadFromStream und SaveToStream virtual (damit die untergeordneten
Klassen sie Überschreiben können) und abstract (so brauch diese Methode erst in
der abgeleiteten Klasse definiert werden).

TObjectClassRef:
Vordefinierung für eine Classenrefernz. Durch das Wörtchen "of" ermöglicht
dieser Typ die polimorphen Objecte.

TName:
Ableitung des TBaseObjectes. Hier werden alle gewünschten Eigenschaften,
Methoden usw. eingetragen. Durch die Methoden SafeToStream und LoadFromStream
erhält das Object die gewünschte Speicher-/Ladefunktion. Diese Methoden müssen
jedoch für jede Ableitung des TBaseObjectes speziell definiert werden.

Nutzung:

Hinzufügen von Daten erfolgt wie üblich bei einer ObjectList.
Bespiel:
Name := TName.Create;
Name.ID := 0;
Name.Name := 'Egon';
Name.Herkunft := 'Deutschland';
Name.Geschlecht := true;
ObjectListe.Add(Name);

Auslesen ist schon schwiriger. Hier muß immer der Typ der Basisklasse der
Procedur bekannt sein.
Bespiel:
Name := ObjectListe.Items[index] as tname;
showmessage(Name.name);

Speichern in Dateien ist auch nicht schwer:
Beispiel:
ObjectListe.SaveToFile('Test.dat');

Dazu das Laden:
Beispiel:
ObjectListe.LoadFromFile('Test.dat');

ObjectListe in einen Stream speichern:
Beispiel:
ObjectListe.SaveToStream(aStream);

ObjectListe aus einen Stream lesen:
Beispiel:
ObjectListe.LoadFromStream(aStream);

Delphi-Quellcode:
unit daten;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, Menus, StdCtrls, Contnrs;


// Basisklassen
 type
  TBaseObject = class (TPersistent)
  protected
    procedure LoadFromStream(Reader:TReader); virtual; abstract;
    procedure SaveToStream(Writer:TWriter); virtual; abstract;
  end;

//Referenztyp zur Klassifiezirung der Daten
 type
  TObjectClassRef = Class of TBaseObject;
//Hier werden die unterschiedlichen Typen des BaseObjects deklariert
//Die Namen der TBaseObject-Ableitungen MÜSSEN einzigartig sein!
  TName = class(TBaseObject)
   private
    fID : Integer;
    fName : String;
    FHerkunft : String;
    fGeschlecht : Boolean;
   protected
    procedure LoadFromStream(Reader:TReader); override;
    procedure SaveToStream(Writer:TWriter); override;
   public
    property ID : Integer Read fID Write fID;
    property Name : String Read fName Write fName;
    property Herkunft : String Read fHerkunft Write fHerkunft;
    property Geschlecht : Boolean Read fGeschlecht Write fGeschlecht;
   end;

//Und natürlich das wichtigste. Die Objectliste, mit der gearbeitet wird.
//Hiervon können natürlich weitere Objecte abgeleitet werden.
 type
  TMyObjectList = class(TObjectList)
  private
  protected
    function GetItem(Index:Integer):TBaseObject;
    procedure RegisterObjects;
  public
    constructor Create;
    function Add(AObject:TBaseObject):Integer;
    procedure LoadFromStream(Stream:TStream);
    procedure SaveToStream(Stream:TStream);
    procedure LoadFromFile(FileName:String);
    procedure SaveToFile(FileName:String);
    property Items[Index:Integer]:TBaseObject read GetItem;
  end;

implementation

procedure TName.LoadFromStream(Reader:TReader);
begin
  //Hier werden die Daten aus den Reader gelesen
  fID := Reader.ReadInteger;
  fName := Reader.ReadString;
  fHerkunft := Reader.ReadString;
  fGeschlecht := Reader.ReadBoolean;
end;

procedure TName.SaveToStream(Writer:TWriter);
begin
//Hier werden die Daten in den Writer geschrieben
  Writer.WriteInteger(fID);
  Writer.WriteString(fName);
  Writer.WriteString(fHerkunft);
  Writer.WriteBoolean(fGeschlecht);
end;

{ Nicht zugeordnete Methoden }

procedure WriteClassRef(Writer: TWriter; o: TObject);
begin
  // Bestimmen und Schreiben des Klassennamens
  Writer.WriteString(o.ClassName);
end;

function ReadClassRef(R: TReader): TClass;
var
  ClassName: String;
begin
  //Auslesen des KlassenNamens
  ClassName := R.ReadString;
  //Rückgabe des Klassennamens
  Result := FindClass(ClassName);
end;

{ Methoden der Basisklasse Objectliste }

constructor TMyObjectList.Create;
begin
  //Aufrufen der ererbten Methode Create
  inherited Create(true);
end;

procedure TMyObjectList.RegisterObjects;
begin
  //Registrierung der TBaseObject-Ableitungen
  RegisterClass(TName);
end;

function TMyObjectList.Add(AObject:TBaseObject):Integer;
begin
  //Hinzufügen eines TBaseObjectes zur Objectliste
  result:=inherited Add(AObject);
end;

function TMyObjectList.GetItem(Index:Integer):TBaseObject;
begin
   //Rückgabe eines TBaseObjectes durch die ererbte Methode Items[index]
   result:=TBaseObject(inherited Items[Index]);
end;

procedure TMyObjectList.LoadFromStream(Stream:TStream);
var
  i : Integer;
  NewObjectRef : TObjectClassRef;
  Reader : TReader;
  NewObject : TBaseObject;
begin
  //Aufruf der nachträglichen Registrierung der TBaseObject
  RegisterObjects;
  //Erstellen eines Readers
  Reader := TReader.Create(Stream, 1024);
  //Löschen des aktuellen Inhalts der aktuellen ObjectList
  Clear;
  //Auslesen der Menge der abgespeicherten Objecte
  count := Reader.ReadInteger;
  for i:=0 to count-1 do begin
    //Auslesen des Typs der TBaseObject-Ableitung
    NewObjectRef := TObjectClassRef(ReadClassRef(Reader));
    //Erstellen eines neuen Instanz dieser Ableitung
    NewObject := NewObjectRef.Create;
    //Auslesen der gespeicherten Informationen
    NewObject.LoadFromStream(Reader);
    //Einfügen an ausgeleser Position in der Objectliste
    Insert (i, NewObject);
  end;
  //Freigabe des Readers
  Reader.Free;
end;

procedure TMyObjectList.SaveToStream(Stream:TStream);
var
  i,c : Integer;
  Writer : TWriter;
begin
  // Erstellen eines TWriters
  writer := TWriter.Create(Stream, 1024);
  // Abfrage, wie viele Objecte die Objectliste enthält
  c:=Count;
  // Schreiben der Objectanzahl
  Writer.WriteInteger(C);
  for i:=0 to c-1 do begin
    // Schreiben des TBaseObjects-Typen-Namen
    WriteClassRef(Writer, Items[i]);
    // Speichern der gewünschten Informationen
    Items[i].SaveToStream(Writer);
  end;
  // Freigabe des Writers
  Writer.Free;
end;

procedure TMyObjectList.LoadFromFile(FileName:String);
var
  Stream : TFileStream;
begin
  // Öffnen der Datei
  Stream := TFileStream.Create(FileName, fmOpenRead);
  // Aufruf von LoadfromStream, da alle notwendigen Funktionen hier schon
  // definiert wurden
  LoadFromStream(Stream);
  // Freigabe des Streams
  Stream.Free;
end;

procedure TMyObjectList.SaveToFile(FileName:String);
var
  Stream : TFileStream;
begin
  // Erzeugen einer leeren Datei
  Stream:= TFileStream.Create(FileName, fmCreate);
  // Aufruf von SaveToStream, da alle notwendigen Funktionen hier schon
  // definiert wurden
  SaveToStream(Stream);
  // Freigabe des Streams
  Stream.Free;
end;


end.
[edit=Chakotay1308]SourceCode korrigiert und Hinweise eingefügt. Mfg, Chakotay1308[/edit]
Marco
Wer Rechtschreibfehler findet, der darf sie behalten

Carpe Diem - Nutze den Tag (und zwar den ganzen!)
  Mit Zitat antworten Zitat
Antwort Antwort

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:35 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz