![]() |
Serialisieren eines Objektes unter D7
Folgendes:
Ich hab ein Proggi dessen Einstellungen ich gerne in einem Objekt verwalten möchte. Problem: Wie speichere ich dieses Objekt? :roll: Nach etwas suchen bin ich auf ein Tut bei delphi-source.de gestoßen ,in dem beschrieben wird wie man mit einem .NET-Delphi Objekte in Form einer XML Datei speichert. Nun habe ich leider kein D8 und habe auch keine große Lust alle möglichen Daten "per Hand" in einen Stream oder eine Ini zu verfrachten. :coder: Frage: Gibt es eine Kompo oder so die mir die Arbeit unter D7 abnimmt? :mrgreen: |
Re: Serialisieren eines Objektes unter D7
Schau mal in die unit typinfo. Dort sind Funktionen um eine Liste aller published Properties zu erhalten und Properties anhand eines String auszulesen bzw. zu setzen. Dann brauchst du ja nur noch in einer Schleife durchgehen und die Werte bzw verlinkten Objekte abspeichern.
|
Re: Serialisieren eines Objektes unter D7
|
Re: Serialisieren eines Objektes unter D7
|
Re: Serialisieren eines Objektes unter D7
@ LarsMiddendorf:
Öm :gruebel: Ich könnte mein Objekt wie gesagt einfach um ne Prozedur erweitern die dann alle Properties in nen Stream schreibt. Das würde doch aufs gleiche rauskommen oder? Doch wie gesagt bzw. gefragt: Gibts denn da keinen einfacheren Weg wie unter Delphi-.Net? |
Re: Serialisieren eines Objektes unter D7
Habe ich das mit dem Collection-Ding richtig verstanden das man das Objekt vom Type TCollechtionItem abstammen lässt und es sich dann somit an das TCollection übergeben lässt womit man es dann speichern kann? *kopfrauch*
P.S.: Thx für die schnelle, gute und zahlreiche Hilfe! :dp: |
Re: Serialisieren eines Objektes unter D7
Da du eine Liste mit den Properties als Array erhältst, brauchst du die Funktion ja nur einmal schreiben und die funktioniert dann mit allen Klassen.
|
Re: Serialisieren eines Objektes unter D7
Ich verstehe...
Aber wie sieht das dann mit dem Laden aus? Und was ist wenn eine Property ein array vom Typ eines anderen Objekts ist? |
Re: Serialisieren eines Objektes unter D7
Zitat:
|
Re: Serialisieren eines Objektes unter D7
Also:
Ich hab ein Objekt das von TCollectionItem abstammt. Dieses hat eine Property welche ein array vom Typ eines anderen Objektes ist. Und wenn das vom Typ TCollection abstammt geht das? :?: *mal rum bastelt* |
Re: Serialisieren eines Objektes unter D7
Zitat:
|
Re: Serialisieren eines Objektes unter D7
Zitat:
Bei einem Array musst du viel zu Fuss machen um Objekte zu entfernen oder hinzuzufügen, eine Collection bringt dir diese Funktionen frei Haus. ;) |
Re: Serialisieren eines Objektes unter D7
Oki...
Ich geb mich geschlagen... Leider im doppelten Sinne: Ich scheitere an der Umsetzung. Vielliecht könnt ihr mir nochmal helfen. :wiejetzt: Also ich hab 3 Objekte. - Objekt(2) hat eine Eigenschaft (-> array, Collection oder wie auch immer) aufgebaut aus Objekten(3) - Objekt(1) hat eine Eigenschaft (-> array, Collection oder wie auch immer) aufgebaut aus Objekten(2) Wer muss nun welchen Typ haben? Sry aber ich blickt durch das System nich so ganz durch... :wall: :wall: :wall: |
Re: Serialisieren eines Objektes unter D7
Hallo,
in der zip-Datei aus der Codelibrary ist eine Powerpoint Datei enthalten. CollectionsItems.ppt. Da habe ich versucht zu zeigen, wie man ein 2-dimensionales "Array" aufbaut. |
Re: Serialisieren eines Objektes unter D7
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ich habe mal ein kleines Beispiel gebastelt. Hier die unit für das 2-dimensionale Array:
Delphi-Quellcode:
Das ist grundsätzlich alles !!!!!!!!!
unit TwoD_Array;
interface uses classes, dpcollection; Type TDimension_2 = class(TCollectionItem) private FText: String; public procedure Assign(Source : TPersistent); override; published property Text: String read FText write FText; end; TDimension_1 = class(TCollectionItem) private FD2Collection : TJsCollection; FName: String; public constructor Create(Collection: TCollection); override; destructor Destroy; override; procedure Assign(Source : TPersistent); override; published property Name : String read FName write FName; property D2 : TJsCollection read FD2Collection write FD2Collection; // Dies ist die 2. Dimension !!! end; implementation { TDimension_1 } procedure TDimension_1.Assign(Source: TPersistent); {Wenn Assign nicht überschrieben wird, werden die eigenen Eigenschaft bei einem Aufruf von Assign auch mit erfasst} begin If Source is TDimension_1 then begin FName:=TDimension_1(Source).Name; FD2Collection.Assign(TDimension_1(Source).D2); end else inherited Assign(Source); end; constructor TDimension_1.Create(Collection: TCollection); begin inherited Create(Collection); FD2Collection:=TJsCollection.Create(TDimension_2); end; destructor TDimension_1.Destroy; begin FD2Collection.Free; inherited Destroy;; end; { TDimension_2 } procedure TDimension_2.Assign(Source: TPersistent); begin If Source is TDimension_2 then begin FText:=TDimension_2(Source).Text; end else inherited Assign(Source); end; end. TDimension_1 ist die 1. Dimension des "Arrays". Dieses Objekt kann hier lediglich einen Namen aufnehmen. Das wäre vergleichbar mit
Delphi-Quellcode:
Jetzt hat TDimension_1 die Eigenschaft D2. Das ist die 2. Dimension. Über D2 können dem Element (Objekt) aus TDimension_1 beliebig viele Strings (Eigenschaft Text von TDimension_2) zugeordnet werden.
sArray : TArray of String;
Jetzt kommt der Source des Beispiels. Ich habe alle Codezeilen, die nichts mit der Anwendung von dbCollection zutun haben weggelassen.
Delphi-Quellcode:
Wie hier zu erkennen ist reicht ein simples LoadFromFile / SaveToFile aus,
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, TwoD_Array, dpcollection, StdCtrls, XPMan; type TForm1 = class(TForm) ... private { Private-Deklarationen } FApplicationPath : String; FCollection : TJsCollection; FD1_Item : TDimension_1; ... public { Public-Deklarationen } end; procedure TForm1.FormCreate(Sender: TObject); begin FCollection:=TJsCollection.Create(TDimension_1); //X ... end; procedure TForm1.FormDestroy(Sender: TObject); begin FCollection.Free; //X end; procedure TForm1.Button1Click(Sender: TObject); begin // erzeuge ein Element (Objekt) in der 1. Ebene FD1_Item:=FCollection.Add as TDimension_1; //X FD1_Item.Name:=edtName.Text; //X end; procedure TForm1.btnTextClick(Sender: TObject); var D2_Item : TDimension_2; begin // Hier wird jetzt die 2. Dimension gefüllt If FD1_Item<>Nil then begin D2_Item:=FD1_Item.D2.Add as TDimension_2; //X D2_Item.Text:=edtText.Text; //X end; end; procedure TForm1.btnSaveClick(Sender: TObject); begin FCollection.SaveToFile(FApplicationPath+'Testdatei.clc'); //X // Die Endung .clc ist hier natürlich völlig willkürlich gewählt end; procedure TForm1.btnLoadClick(Sender: TObject); begin FCollection.LoadFromFile(FApplicationPath+'Testdatei.clc'); //X end; end. um das "Array" zu speichern oder zu laden. Aber jetzt kommt der eigenliche Hammer !!! Nehmen wir einmal an, Du möchtest zu jedem Element (Objekt) der 1. Dimension in der 2. Dimension beliebig viele Bitmaps speichern !!! MIt der dpCollection ist das überhaupt kein Problem. Ich werde jetzt die Klasse TDimension_2 so erweitern das auch Bitmaps gespeichert werden können. D.h. das Speichern und Laden geschieht dann völlig automatisch!
Delphi-Quellcode:
Das ist alles !!!
TDimension_2 = class(TCollectionItem)
private FText: String; FBitmap: TBitmap; procedure SetBitmap(const Value: TBitmap); public constructor Create(Collection: TCollection); override; destructor Destroy; override; procedure Assign(Source : TPersistent); override; published property Bitmap : TBitmap read FBitmap write SetBitmap; property Text: String read FText write FText; end; ... constructor TDimension_2.Create(Collection: TCollection); begin inherited Create(Collection); FBitmap:=TBitmap.Create; end; destructor TDimension_2.Destroy; begin FBitmap.Free; inherited Destroy; end; procedure TDimension_2.Assign(Source: TPersistent); begin If Source is TDimension_2 then begin FBitmap.Assign(TDimension_2(Source).Bitmap); FText:=TDimension_2(Source).Text; end else inherited Assign(Source); end; procedure TDimension_2.SetBitmap(const Value: TBitmap); begin FBitmap.Assign(Value); end; So lassen sich alle Nachfahren von TPersistent speichern Jetzt kommt der 2. Hammer!!! Durch die Einführung der Bitmap wurde das Dateiformat geändert. Mit einer typisierten Datei hätte man das Problem, dass das neue Programm die alten Dateien nicht ohne weiteres lesen kann. Nicht so mit der dpCollection. Die dpCollection verwendet das Delphi-Streamingsystem (das ist das Ding, das dafür sorgt, das die Formulare mit all den Komponenten und Einstellungen die Ihr gemacht habt in der dfm-Datei landen). D.h. es werden nur die Eigenschaften aus der Datei gelesen, die auch in der Datei enthalten sind. Die Eigenschaften, die nicht in der Datei sind erhalten den Standardwert. D.h. mit der dpCollection seit Ihr automatisch Abwärtskompatibel. |
Re: Serialisieren eines Objektes unter D7
So...
Ich hab das ganze nochmal für mich nachvollziehbarer nach geproggt und muss sagen: Respekt! :thumb: Das ist wenn man es verstanden hat wirklich einfach! Big Thx für eure große Hilfe! :dp: |
Re: Serialisieren eines Objektes unter D7
Hmm...
Ein Problem hab ich doch noch: Ich möchte in einer procedure von einem Item auf eine Eigenschaft des Objekts zugreifen, welches das Array mit eben diesem Item als Inhalt als property besitzt. Falls ihr das verstanden habt: Geht das? |
Re: Serialisieren eines Objektes unter D7
Zitat:
|
Re: Serialisieren eines Objektes unter D7
Liste der Anhänge anzeigen (Anzahl: 1)
Also:
Ich habe ein Objekt(1) das hat eine Property vom Typ TjsCollection. Dann habe ich ein Objekt(2) das von TCollectionItem abstammt und in dieser Collection-Property des anderen Objektes(1) ist. Außerdem hat das Objekt(2) noch eine Prozedur. Nun kommt das knifflige: Ich möchte in dieser Prozedur aus Objekt(2) auf eine Property aus dem Objekt(1) zugreifen, in dem sich mein Aktuelles Objekt 2 als Item in der Property befindet. Ich hab direkt ma ne Zeichnung gemacht :mrgreen: |
Re: Serialisieren eines Objektes unter D7
Hallo,
wenn ich das richtig sehe möchtest Du von einem TCollectionItem aus auf eine Eigenschaft der Collection zurgreifen, die das TCollectionItem verwaltet. Kein Problem. Dafür gibt es
Delphi-Quellcode:
TCollectionItem.Collection.HierDieEigenschaftAngeben
|
Re: Serialisieren eines Objektes unter D7
Also es gibt die Eigenschaft aber ich kann sie irgendwie nicht verwenden. Sie wird auch in der Programmierhilfe nicht angezeigt... :gruebel:
Zitat:
|
Re: Serialisieren eines Objektes unter D7
Moin,
da kommt unsere geliebte Collection ja mal wieder zu ehren :-D Vielleicht könnte man diesen thread mit dem der CodeLib verbinden, denn hier sammeln sich ja schon interessante fakten. Zum problem, wenn du aus dem item, auf eine property der collection zugreifen willst, dann musst du 'casten'. Oder entsprechende kapselungen bereitstellen. Ungefähr so:
Delphi-Quellcode:
ich hoffe deine frage zielte auf soetwas ab? Davon abgesehen würde ich TmxJsCollection benutzen, da die daten somit als text gespeichert werden können, was in der entwicklung ein schnelles einsehen und modifizieren ermöglicht :-D
type
// Angenommen das ist deine CollectionKlasse TMyCollection = class(TmxJsCollection) ... published property MyProp:TFoo read etc.. end; // angenommen das ist deine itemklasse TMyItem = class(TCollectionItem) private function GetMyCollection:TMyCollection; public property MyCollection: TMyCollection read GetMyCollection; // collection gecasted kapseln end; function TMyItem.GetMyCollection:TMyCollection; begin result := (Collection as TMyCollection); end; .... // jetzt kannst du aus jedem item einfach, die properties der collection abrufen, ohne jedesmal explizit zu casten: MyCollection.MyProp := bar; |
Re: Serialisieren eines Objektes unter D7
Hallo,
wenn ich mir die Zeichnung anschaue, dann vermute ich das Mr_G soetwas meint:
Delphi-Quellcode:
Jetzt möchte Mr_G über SubCollection_1 auf XYZ Zugreifen.
TSubCollection_1_Item = class(TCollectionItem) // wird von SubCollection_1 verwaltet !!!
... TCollection_1 =class(TmxJsCollection) private FSubCollection_1 : TmxJsCollection; FXYZ : Integer; public property SubCollection_1 : TmxJsCollection read FSubCollection_1 write FSubCollection_1; property XYZ: Integer read FXYZ write FXYZ; end; SubCollection_1.Collection. weiter kommt Mr_G z.Z. noch nicht. Jetzt würde ich für SubCollection_1 einen Nachfahren von TmxJsCollection basteln. Diesem Nachfahren würde ich eine Parent Eigenschaft verpassen
Delphi-Quellcode:
Jetzt geht folgendes:
TSubCollection_1_Item = class(TCollectionItem) // wird von SubCollection_1 verwaltet !!!
... TCollection_1 =class; TmxJsCollectionParent=class(TmxJsCollection) private FParent : TCollection_1; public property Parent : TCollection_1 read FParent write FParent; end; TCollection_1 =class(TmxJsCollection) private FSubCollection_1 : TmxJsCollectionParent; FXYZ : Integer; public constructor Create(ItemClass : TCollectionItemClass); property SubCollection_1 : TmxJsCollectionParent read FSubCollection_1 write FSubCollection_1; property XYZ: Integer read FXYZ write FXYZ; end; ... TCollection_1.constructor.Create(ItemClass : TCollectionItemClass); begin inherited Create(ItemClass); FSubCollection_1:=TmxJsCollectionParent(TSubCollection_1_Item); FSubCollection.Parent:=Self; // Hier ist es !!!!!!!! ... end;
Delphi-Quellcode:
(ungetested)
TmxJsCollectionParent(TSubCollection_1_Item.Collection).Parent.XYZ
|
Re: Serialisieren eines Objektes unter D7
Ahso, ich hab dieses problem immer mit TOwnedCollection gelöst. Dazu hab ich einfach den vorfahr von TJsCollection geändert. So kann man schön auf den owner zugreifen, auch wenn es konzeptionell nicht so schön ist. Letzendlich kommt es immer drauf an, was man erreichen will...vielleicht denkt Mr_G da auch zu kompliziert (soll ja vorkommen) und es gibt eine einfache lösung?
|
Re: Serialisieren eines Objektes unter D7
Zitat:
|
Re: Serialisieren eines Objektes unter D7
Hmmm
Ersma Sorry das ich mich so lange nich gemeldet hab (Grippe :cry: )... Nun aber wieder zum Thema: Welche der Lösungen ist für mein beschriebenes Problem nun die beste und falls es die mit TOwnedCollection ist, wie benutze ich das :?: Nochmal danke der Hilfe :thumb: |
Re: Serialisieren eines Objektes unter D7
Zitat:
|
Re: Serialisieren eines Objektes unter D7
Zitat:
|
Re: Serialisieren eines Objektes unter D7
Da ich mich aus zeitmangel erst jetzt wieder mit dem Thema beschäftigt habe, habe ich nun immernoch ein Problem:
Ich habe das mit der OwnedCollection gemacht, was auch so aussieht als sei es die Perfekte Lösung meines Problems. Leider kann ich sie nicht umsetzen weil meinem Objekt mit dem Vorfahren TCollectionItem die Eigenscaft Collection fehlt. Ich kann besagte Eigenschaft einfach nicht nutzen (wird u.A. von der Programmierhilfe auch nicht angezeigt). Daraus folgt das ich natürlich auch nicht auf den Owner meiner Collection zugreifen kann was ich ja erreichen wollte... Was könnte ich falsch gemacht haben? :cry: |
Re: Serialisieren eines Objektes unter D7
Hallo,
da TCollectionItem die property Collection hat, haben alle Nachkommen diese property. Die property Collection ist aber vom Type TCollection evt. muss Du für den Zugriff noch auf Deinen TCollection Nachfahren casten. |
Re: Serialisieren eines Objektes unter D7
Zitat:
Wie macht man das? |
Re: Serialisieren eines Objektes unter D7
Zitat:
Code:
TMyCollection(CollectionItem.Collection).Irgendwas
|
Re: Serialisieren eines Objektes unter D7
Zitat:
Mein CollectionItem hat warum auch immer kein ".Collection"! :cry: |
Re: Serialisieren eines Objektes unter D7
Zitat:
Zeig mal den Sourcecode |
Re: Serialisieren eines Objektes unter D7
Hier die definition des eigenen Typs aus meinem Testprojekt:
Code:
Falls das ganze Projekt brauchst nur bescheid sagen ...
type TPerson = class(TCollectionItem)
private FName:String; FAlter:Integer; public procedure Assign(Source: TPersistent); override; procedure DoATest; published property Name: String read FName write FName; property Alter: Integer read FAlter write FAlter; end; |
Re: Serialisieren eines Objektes unter D7
Hallo,
Code:
type TPerson = class(TCollectionItem)
private FName:String; FAlter:Integer; public procedure Assign(Source: TPersistent); override; procedure DoATest; published property Name: String read FName write FName; property Alter: Integer read FAlter write FAlter; end; // Nehmen wir mal, Dein TCollection-Nachfahre wäre folgender TMyCollection = class(TCollection) public procedure DoSomething; ... //Wenn Du innerhalb einer TPerson Methode auf Dein TMyCollection Objekt // Zugreifen möchtest musst Du folgendes schreiben. procedure TPerson.DoATest; begin TMyCollection(Collection).DoSomething; end; |
Re: Serialisieren eines Objektes unter D7
Dazu müsste man aber doch dann die Instanz kennen und das war ja mein Problem... ...oder verstehe ich da etwas falsch?
|
Re: Serialisieren eines Objektes unter D7
Zitat:
Wenn Du zu einer TCollection ein TCollectionItem hinzufügst (Methode Add) wird automatisch die Collection property des TCollectionItems gesetzt. Somit ist die Collection innerhalb des TCollectionItems bekannt. Schau Dir doch mal den TCollection / TCollectionItem Sourcecode an. Oder geh mal mit dem Debugger Schritt für Schritt das Hinzufügen eines TCollectionItems an. |
Re: Serialisieren eines Objektes unter D7
Ok...! Ich habs! :thumb:
Ich bin eben einfach zu dumm für diese Welt! :wall: :wall: :wall: P.S.: Danke für die unermüdliche Hilfe! :dp: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:32 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz