Hallo Hagen
Vien Dank für Deine ausführliche Beschreibung!! Du hast recht, mit den Internals von Klassen habe ich mich noch nicht vertraut gemacht.
Deine Lösung kann ich sehr gut nachvollziehen. Die Geschwindigkeit ist bestimmt deutlich besser als wenn man mit bei jedem Objekt mit Strings operieren muss.
Nachdem du den Lösungsweg so ausführlich bechrieben hast, für andere hier im Forum, welche diesen Weg gehen möchten, "ganz grob " mein Verständnis der Umsetzung:
1.) Schreibe die Objekte mit deren Indizess in ein Stream.
Delphi-Quellcode:
var ClsAry:Array[0..MaxClasses] of TMyClass; // über die Klassen in diesem Array erfolgt der Zugriff beim Lesen
ClsNameAry:Array[0..MaxClasses] of ShortString; // dieses Array wird an das Ende des Streams geschrieben
// Schreibe die Daten in ein Stream
Stream:=TStream.Create(.....);
Stream.Write(AnzElemente,Sizeof(AnzElemente));
for i:=0 To AnzElemente-1 Do
Begin
El:=ElementeList[i];
ClsIdx:=GetClassIndex(El); // prüfe ob die Klasse in ClsAry bereits vorhanden ist, ansonsten lege den Klassenamen an
// hier nicht implementiert
Stream.Write(ClsIdx,SizeOf(ClsIdx));
End;
ClsTableOffsett:=stream.Position; // merke den Offsett, an dem die Klassentabelle abgelegt ist
Stream.Write(MaxClasses,sizeof(MaxClasses)); // schreibe Anzahl der Elemente an Klassennamen
for i:=0 To MaxClasses-1 Do // schreibe die Klassentabelle
Begin
len:=length(ClsNameAry[i];
Stream.Write(len,sizeof(len));
Stream.Write(ClsNameAry[i],len);
End;
Stream.Write(ClsTableOffsett,sizeof(ClsTableOffsett)); // schreibe den Offsett der Tabelle in den Stream
//Restore
// Auslesen der Klassenbeschreiber
Stream.Position:=Stream.Size-4); // lies Offsett der KlassenNamen aus dem Stream
Stream.Read(ClassTableLen); // lies Anzahl der Elemente an Klassen
Stream.Positio:=Stream.Size-ClassTableLen*4-4;
for i:=0 to ClassTableLen-1 Do // Idendifiziere die Zeiger auf die Klassen
Begin
Stream.Read(ClsStrLen,sizeof(ClsStrLen));
Stream.Read(ClassNameStr,sizeof(ClsStrLen));
ClsAry[i]:=FindClass(ClassNameStr); // rufe die Hagensche Funktion auf:)
End;
// Auslesen der Daten
Stream.Position:=0;
Stream.Read(AnzElemente,SizeOf(AnzElemente));
For i:=0 To AnzElemente-1 DO
Begin
Stream.Read(ClsIdx,Sizeof(ClsIdx));
ClsAry[ClsIdx].Load(s); // unter der Voraussetzung, dass die Komponenen von TMyClass über eien Load-Methode verfügen
End;
Anmerkungen dazu:
1.) Die Klassentabelle könnte man auch bei der Initialisierung des Programmes anlegen (Nachteil, man muss dann u.U. die gesamte Klassentabelle im Stream ablegen.
2.) Man könnte den Index eines Objektes auch in die Klassen verankern und gleich zu beginn setzen. Dann erspart man
sich die Suche in der Tabelle identifizierter Klassen beim Schreiben des Streams, dann aber wieder mit dem Nachteil, dass der Aufand für die Wartung steigt.
3.) Im Code oben habe ich das Klassenarray nicht vom Type TClass verwendet. Ginge auch, auf diese Weise kann man aber unmittelbar auf Methoden zugreifen.
Beste Grüsse
Geri