|
Antwort |
Registriert seit: 3. Jan 2007 Ort: Dresden 3.443 Beiträge Delphi 7 Enterprise |
#1
Beschreibung
Jede Klasse, die von TCustomStore (siehe Anhang) abgeleitet wird kann sich komplett selber in einen Stream (oder nonVCL-Unit: in einen String) speichern, und natürlich auch davon wiederherstellen. Und dabei ist es völlig irrelevant, welche Variablen als Properties definiert wurden. Es werden alle Variablen gespeichert. Diese Varibalen können statisch oder dynamisch sein, also alles was Delphi so an Typen kennt inkl. Records und weiterer Klassen. (Es können aber auch einzelne Variablen davon ausgenommen werden) Anwendung Ich stelle einfach kurz ein Beispiel vor:
Delphi-Quellcode:
//Diese Klasse ist von TCustomStore abgeleitet und bringt deswegen die Methoden
//SaveToStream und LoadFromStream mit. //die nonVCL-Variante muss natürlich ohne Stream auskommen und verwendet daher Strings type TStore=class(TCustomStore) public i:integer; Store2:TStore_2; Strings:TStrings; other_class:TMyOwn; p:pointer; //der soll in diesem Beispiel nicht gespeichert werden constructor create; //Im constructor werde ich hier die Klassen registrieren. //Dies kann allerdings auch später passieren. end; constructor TStore.create; begin inherited create; Store2:=TStore2.Create; Strings:=tstringlist.Create; other_class:=tmyown.Create; //der wichtige Teil, der gemacht werden muss, da Klassen nicht in der RTTI enthalten sind RegisterObject(@Store3); //die Registrerung über RegisterObject geht für Klassen, die // -von TCdustomStore abgleitet sind // -keine dynamischen Varibalen enthalten // -mittels der Ereignisbehandlung ClassSaveEvent und ClassLoadEvent gespeichert werden //Für andere Klassen müssen die Stream-Methoden mit angegeben werden //die Methoden müssen vom Typ "procedure(Stream:TStream) of object" sein //Der Stream, der übergeben wird ist exklusiv, mann muss sich also nicht die Länge merken RegisterobjectMethod(@other_class, other_class.Save, other_class.Load); RegisterObjectMethod(@Strings, Strings.SaveToStream, Strings.LoadFromStream); //und noch Variablen/Klassen registrieren die nicht gespeichert werden sollen //in dem Fall, der untypisierte pointer Registerdontsave(@p,sizeof(p)); //letztenendes bedeutet dies Registrierung, dass der pointer durch //LoadFromStream nicht überschrieben wird //Klassen innerhalb von Records und dynamischen Arrays können nicht registriert werden //und sollten daher nicht verwendet werden --> in eine Klasse kapseln //RegisterDontSave ist nur für Pointer und Klassen gedacht //--> geht definitiv nicht für Records und Dynamische Arrays end; //speichern der Klasse TStore procedure TForm1.SaveButtonClick(Sender: TObject); var Class_to_Store:TStore; File:TFileStream; begin Class_to_Store:=TStore.create; Class_to_Store.i:=9; Class_to_Store.Store2.x:='Hallo'; //eine dynamische String-Variable aus TStore3 belegen Strings.add('Lala'); other_class.s:='Hilfe'; Class_to_Store.p:=pointer(10); File:=TfileStream.Create('Test_SPclass.dat',fmcreate); Class_to_Store.SaveToStream(File); File.free; Class_to_Store.free; //Da Class_to_Store.FreeAllObjects per default auf True ist, werden alle registrierten //Klassen von RegisterObject und RegisterObjectMethods mit freigegeben. //Andere Klassen und Variablen (auch die von RegisterDontSave) müssen selber freigegeben werden end; //Laden der Klasse TStore procedure TForm1.LoadButtonClick(Sender: TObject); var Class_Stored:TStore; File:TFilestream; begin memo1.clear; Class_Stored:=TStore.create; Class_Stored.i:=-1; //zum Test, dass sich nach loadfromstream auch etwas ändert Class_Stored.x:='Das will ich gleich nicht mehr sehen'; Class_Stored.p:=pointer(50); //Der sollte gleich bleiben File:=TfileStream.Create('Test_SPclass.dat',fmopenread); Class_Stored.LoadfromStream(File); File.free; memo1.lines.add(Class_Stored.Store2.x); memo1.lines.Add(inttostr(Class_Stored.i)); memo1.lines.AddStrings(Class_Stored.Strings); memo1.lines.Add(Class_Stored.other_class.s); memo1.lines.add(inttostr(integer(Class_Stored.p))); Class_Stored.free; end;
Delphi-Quellcode:
//hie noch die Testklassen, die in der eigentlichen Klasse verwendet werden type tmyown=class s:string; procedure save(Stream:Tstream); procedure Load(Stream:Tstream); end; type TStore2=class(TCustomStore) public x:string; end; //Methoden der HilfsTestKlassen procedure TmyOwn.save; begin stream.Write(s[1],length(x)); end; procedure Tmyown.Load; begin setlength(s,stream.size); stream.read(s[1],length(s)); end; Soweit dazu. Ansonsten noch der Text, der auch in der Unit steht:
Zitat:
unit U_Store_Classes
benötigt U_Store_Dynamic_Params Inhalt ====== class "TCustomStore" Beschreibung ============ Klassen, die von TcustomStore abgeleitet werden bringen folgende zwei Methoden mit -SaveToStream -LoadFromStream Damit wird der komplette Inhalt (Records, strings, dynamische arrays, ...) der Klasse im Stream gespeicher bzw. aus dem Stream geladen. Dies geschieht unabhängig von den definierten Properties. Zusätzlich werden alle registrierten Klassen die in der Basisklasse enthalten sind, gespeichert/geladen. Je nach Einstellung von der Eigenschaft FreeallObjects werden alle registrierten Objekte freigegeben Verwendung ========== type TTest=class(TCustomStore) private x:integer; t:string; n:array of string; Int_Store:TStore; //abgeleitet von TCustomStore myclass:Tmyclass; p:pointer; timer:Ttimer; public //... hier können auch weiter Variablen stehen constructor create; override; end; //.... constructor TTest.create; begin list:=Tstringlist.create; myclass:=tmyclass.create; //ganz wichtig, jede Klasse muss vor der Verwendung von //savetostream/loadfromstream registriert werden RegisterObject(@int_Store); //dies gilt nur für bestimmte Klassen (siehe unten) //alternativ können auch Klasse (und auch Variablen, wie pointer) //als Don't-Save registriert werden. //Dadurch wird beim Laden, der ursprüngliche Inhalt in der Klasse nicht überschrieben RegisterdontSave(@p,sizeof(p)); Registerdontsave(@timer) //size=4 ist standard für Klassen //Hierbei ist die Größe der Variablen anzugeben //Klassen, die nicht wie oben registriert werden können //und ihre eigenen SaveToStream und LoadFromStream -methoden mitbringen //können wie folgt registriert werden RegisterObjectMethod(@myclass,myclass.savetostream ,myclass.loadfromstream); end; // Aufruf: var test:Ttest; stream:TFilestream; begin test:=TTest.create; //...Eigenschaften setzen etc. //Zustand speichern stream:=Tfilestream.create('xyz.dat',fmcreate); test.savetofile(stream); stream.free; //... //Zustand wieder laden stream:=Tfilestream.create('xyz.dat',fmopenread); test.Loadfromfile(stream); stream.free; //... test.free; //Die StringList wird auch freigegeben end; Für Klassen innerhalb der Basisklasse, die nicht von TCustomStore abgeleitet werden, kann auch das Ereignis TClassStoreEvent (ClassLoadEvent und ClassSaveEvent) definiert werden. Dieses wird ausgelöst, sobald eine Klasse von RegisterObject gespeichert oder geladen werden soll, die nicht TCustomStore als Vorfahr hat. Diese Ereignisbehandlungsroutine kann dann das Speichern des Objektes übernehmen. Desweiteren können alle Klassen, die in ihren Variablen keine weiteren Klassen enthalten direkt registriert (RegisterObject) werden. Hinweise ======== 1. Klassen müssen mit RTTI compiliert werden (siehe Compilerdirektive $M+) 2. Es können keine Interfaces bearbeitet werden 3. NICHTREGISTRIERTE Klassen werden beim laden wahrscheinlich ungültig ==>Speicherlöcher 4. Eine untergeordnete Klasse, die beim Aufruf von SavetoStream instanziert, war, muss es auch noch/wieder bei LoadfromStream sein. 5. Es wird nicht kontrolliert, ob Variablen/Klassen mehrfach in verschiedenen Listen registriert wurden (sollte vermieden werden, da es zu unerwünschten Effekten kommen kann) 6. Es können keine Klassen innerhalb von dynamischen Komponenten ( Records und dynamischen Arrays) registriert werden 7. RegisterDontSave geht nur für einfache Pointer oder für Klassen Es geht nicht für Records und Arrays. (Ich will die Unit nicht hier nochmal anhängen. Falls ich an ihr noch etwas ändere müsste ich sonst in beiden Threads updaten) Edit 19.7.07 23:15 -- Überarbeitete Version hochgeladen Edit 20.7.07 10:00 -- Noch ein Beispielprojekt angefertigt Edit 08.8.07 21:15 -- nonVCL-Variante ergänzt
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
|
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |