Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi XML Serialisierer für beliebige DelphiObjecte auf RTTI Basis (https://www.delphipraxis.net/129234-xml-serialisierer-fuer-beliebige-delphiobjecte-auf-rtti-basis.html)

stoxx 15. Feb 2009 06:19


XML Serialisierer für beliebige DelphiObjecte auf RTTI Basis
 
Liste der Anhänge anzeigen (Anzahl: 4)
Ich habe da nochmal gebastelt .. wollten sie schonmal ein komplettes Form mit seinen Komponenten in eine XML Datei abspeichern? *grins*

Delphi-Quellcode:
form1.saveToXML(FileName); ??


ich sage mal besser, Code sagt mehr als 1000 Worte

wollten Sie schonmal sowas machen ? :stupid:


Delphi-Quellcode:
//==============================================================================
procedure TfrmXMLSerialisierer.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Self.SaveToXMLContainer('FormAtClose');
end;
//==============================================================================
procedure TfrmXMLSerialisierer.FormCreate(Sender: TObject);
begin
  Self.LoadFromXMLContainer('FormAtClose');
end;


//==============================================================================
procedure TfrmXMLSerialisierer.btnSaveClick(Sender: TObject);
begin
  Self.SaveToXML('Form.xml');
end;
//==============================================================================
procedure TfrmXMLSerialisierer.btnLoadClick(Sender: TObject);
begin
   Self.LoadFromXML('Form.xml');
end;

oder sowas?


Delphi-Quellcode:
TMyEnum = (meNotset, meEnum1, meEnum2);

{$M+} 
TMyClass = class(TPersistent) // wenn der Compiler nicht ab und zu spinnen wuerde
                               // kann man auch TObject benutzen
private
    FString : string;
    FNewDouble: Double;
    FEnum: TMyEnum;
published
  property EnumValue : TMyEnum read FEnum write FEnum;
  property DoubleValue : Double read FNewDouble write FNEwDouble;
  property StringValue : String read FString write FString;
end;



//==============================================================================


procedure TfrmXMLSerialisierer.btnSaveContainerClick(Sender: TObject);
var MyObject : TMyClass;
begin

    edt1.SaveToXML('MyEdit.xml');

    Self.stringgrid1.SaveToXMLContainer('MyStringgrid');


    MyObject := TMyClass.Create;
    MyObject.StringValue := DateTimeToStr(Now);
    MyObject.EnumValue := meEnum1;
    MyObject.DoubleValue := 12345.67;

    MyObject.SaveToXMLContainer('MyClass');

    MyObject.Free;


end;


das Projekt ist im Anhang. Es reicht einfach und immer und überall die Unit uBase_XMLSerializer.pas einzubinden.
Für alle Objecte verfügbar.
Eigene Klassen am besten von TPersistent ableiten.

Mit TObject geht es zwar auch (mit {$M+} vor der Klasse)
Aber ab und zu bringt der compiler bei mir komische Fehlermeldungen, und es lässt sich nicht compilieren, erst nach einem fummeligen Neustart geht es wieder.

Vielleicht sollte man die DCU's einmal compiliert lassen und vielleicht sollte man mal die pas Files verstecken...

Das ganze beruht auf dieser Komponente, die aber noch 4 Schwachstellen hatte, bevor sie wirklich rund lief.

http://blog.dragonsoft.us/2008/04/21...delphi-object/

die genauen Änderungen stehen in der uBase_XMLSerializer.pas.


das war der erste Artikel dazu ..

http://www.delphipraxis.net/internal...t.php?t=152078


sooo .. na viel Spaß :-)
wollte ich schon immermal haben ...

stoxx 25. Feb 2009 16:50

Re: XML Serialisierer für beliebige DelphiObjecte auf RTTI B
 
Liste der Anhänge anzeigen (Anzahl: 2)
die Begeisterung hält sich ja erstaunlicherweise in Grenzen.
Na das werde ich mal versuchen mit einer neuen Version zu ändern :-)

Man kann nette Dinge mit der RTTI anstellen.
Zum Beispiel alle published Properties einfach von einem Object ins andere kopieren.
(man beachte, dass kein assign notwendig ist)
P.S. es gibt eine neue Version vom Original, die modifzierte befindet sich wieder im Anhang

folgendene Definition....

type



Delphi-Quellcode:
TMyEnum = (meNotset, meEnum1, meEnum2);


TInClass = class(TPersistent)
                             
private
    FString : string;
published
  property StringValue : String read FString write FString;
end;


//==============================================================================

TMyClass = class(TPersistent)
                               
private
    FInObj : TInClass;
    FString : string;
    FNewDouble: Double;
    FEnum: TMyEnum;
    FTop: Integer;
published
  constructor create;
  destructor destroy; override;
  function Show : string;

  property EnumValue : TMyEnum read FEnum write FEnum;
  property DoubleValue : Double read FNewDouble write FNEwDouble;
  property StringValue : String read FString write FString;
  property InObject : TInClass read FInObj write FInObj;
  property Top : Integer read FTop write FTop;

end;


implementation

//==============================================================================
{ TMyClass }
//==============================================================================
constructor TMyClass.create;
begin
  inherited create;
//  FInObj := TInClass.Create(self);
//  FInObj.SetSubComponent(true);
  FInObj := TInClass.Create;
end;
//==============================================================================
destructor TMyClass.destroy;
begin

  FInObj.Free;
  inherited;
end;
//==============================================================================

function TMyClass.Show: string;
begin
      ShowMessage(
          'EnumValue: '      + GetEnumName(TypeInfo(TMyEnum ) , integer(Self.FEnum)) + #13#10 +
          'StringValue: '    + self.StringValue + #13#10 +
          'DoubleValue: '    + FloatToStr(self.DoubleValue) + #13#10 +
          'TopValue: '       + IntToStr(self.Top) + #13#10 +
          'InnerClass Value: '+ self.InObject.StringValue);
end;

das ist der Test ...



Delphi-Quellcode:
procedure TfrmXMLSerialisierer.btnCopyPuPropClick(Sender: TObject);
var
  myObject : TMyClass;
  myCopy : TMyClass;

begin


    MyObject := TMyClass.Create;
    myObject.Top := 10;
    myObject.Show;

    // "Top" Property von Form kopieren (ist die einzigste gemeinsame Property"
    // man beachte, es gibt nirgendwo eine Assign Procedure

    myObject.CopyPupProperiesFrom(self);

    MyObject.StringValue := DateTimeToStr(Now);
    MyObject.EnumValue := meEnum1;
    MyObject.DoubleValue := 12345.67;
    MyObject.InObject.StringValue := 'Inner Class';

    myObject.Show;

     // neues Object (Kopie)
     myCopy := TMyClass.create;
     myObject.CopyPupProperiesTo(myCopy);
     myCopy.Show;


    // speichern //
    MyObject.SaveToXML('MyClass.xml');
    MyObject.Free;

    // Laden
    MyObject := TMyClass.Create;
    MyObject.LoadFromXML('MyClass.xml');
    myObject.Show;
    MyObject.Free;
end;

OldGrumpy 13. Mär 2009 15:04

Re: XML Serialisierer für beliebige DelphiObjecte auf RTTI B
 
Klingt als wenn das für eines meiner nächsten Projekte sehr brauchbar wäre :) Vielleicht hält sich die Begeisterung in Grenzen weil es die x-te Implementation der Lösung eines recht alten Problems ist und die meisten daher schon eine eigene Implementation oder andere Lösung gefunden haben :) Ohne konkreten Bedarf würd ich das jetzt auch nicht unbedingt ausprobieren - aber nett ists schon :)

P.S. Liegt vielleicht auch daran, dass ich nicht unbedingt sooo ein XML-Fan bin. XML kann Vorteile haben, aber auf Biegen und Brechen XML als Universallösung für alle Probleme zu verwenden... manchmal könnte man echt den Eindruck bekommen, man dürfte gar nix anderes an Formaten mehr verwenden *g*

Elvis 13. Mär 2009 15:21

Re: XML Serialisierer für beliebige DelphiObjecte auf RTTI B
 
Zitat:

Zitat von OldGrumpy
manchmal könnte man echt den Eindruck bekommen, man dürfte gar nix anderes an Formaten mehr verwenden *g*

IMO sollte man immer wenn man nicht XML nimmt, diese Entscheidung sehr gut rechtfertigen können.
Proprietäre Formate haben weder XSL noch XSD, und sie sind auch nicht so portabel. IOW: Per XSL kann man meine Daten im Browser öffnet und sieht eine UI, die AJAX nutzt zum Browsing/Filtern der Daten.
Wenn ich das einlese kann ich es gegen ein XSD validieren und kriege hübsche, sinnvolle Meldunen. Aber auch andere können das XSD hernehen, da es mein Format exakt dokumentiert...

Möchte keinen Flame lostreten (trotz meiner diesbezüglichen Begabung), aber um es mit Lesch zu sagen:
Es ist halt kein Zufall dass die Katze da Löcher im Fell hat, wo auch ihre Augen sind.

Es ist halt kein Zufall, dass sich XML der aktuellen Beliebtheit erfreut...

DMW 13. Mär 2009 15:39

Re: XML Serialisierer für beliebige DelphiObjecte auf RTTI B
 
SCNR.

OldGrumpy 13. Mär 2009 16:00

Re: XML Serialisierer für beliebige DelphiObjecte auf RTTI B
 
Zitat:

Zitat von Elvis
IMO sollte man immer wenn man nicht XML nimmt, diese Entscheidung sehr gut rechtfertigen können. Proprietäre Formate haben weder XSL noch XSD, und sie sind auch nicht so portabel.[...]

Die Frage ist halt immer: *muss* es das denn sein? Und lohnt es den Entwicklungsaufwand? Ich habe etliche Projekte in denen zum Beispiel a) nur kleine Datenmengen anfallen, und b) die auch nur lokal. Zudem sind die c) sehr stark plattformgebunden. Da lohnt es nicht, den Aufwand für die Migration zu XML zu treiben.

Zumal das größte Problem dabei ist, fast jeder will XML (ob sinnvoll oder nicht), aber kaum jemand versteht es wirklich vollständig :) Ein paar Resultate dieses Umstands findet man z.B. auf dieser wunderschönen Website :mrgreen:

Zitat:

Zitat von Elvis
Es ist halt kein Zufall, dass sich XML der aktuellen Beliebtheit erfreut...

Die Dotcom-Blase war auch kein Zufall... :mrgreen: :twisted:

DerDan 13. Mär 2009 16:57

Re: XML Serialisierer für beliebige DelphiObjecte auf RTTI B
 
Hallo,

wenn man eine Serializer / Deserializer Komponente hat, welche die published Propertiers einer Klasse samt Ableitungen rekursiv in das XML Format schreibt und ließt,
dann braucht man nie wieder etwas anderes.

Sowas kann dann auch dazu benutzt werden, um Daten über die Zwischenablage auszutauschen.


mfg

DerDan

stoxx 13. Mär 2009 20:32

Re: XML Serialisierer für beliebige DelphiObjecte auf RTTI B
 
es geht gar nicht mal so sehr um XML .. man kann auch das Delphi eigene DFM Format nehmen.
Wenn man sucht findet man auch beispiele "ObjectToText" oder so .. nur
leider ist das total schrottig und ohne Anpassungen so nicht nutzbar.
Alte Format Versionen können oft nicht mit neuer Software eingelesen werden.
die Delphieigenen Sachen funktionieren außerdem nur mit TComponent.
Desweiteren bricht bei einem kleinen Fehler gleich die komplette Routine ab, so dass man gar nix einlesen kann, anstatt nur die fehlende property zu übergehen.

Der Witz an dem Serializier ist doch gerade, dass man verionsunabhängig ist. Man übergibt nur TObject und selbst wenn es sich um eine abgeleitete Klasse wie TSTringgrid handelt, werden alle published properties gespeichert, ganz von selbst und vollautomatisch.
Man braucht sich nie wieder umwas gedanken machen.

Mr_G 18. Mär 2009 21:30

Re: XML Serialisierer für beliebige DelphiObjecte auf RTTI B
 
Wie sieht das denn aus wenn ich als published-Property eine Referenz auf ein Objekt hab das auch von TPersistent abgeleitet ist?
Bei einem kurzen Test hat das speichern funktioniert und das Laden einmal funktioniert und einmal gab es eine Zugriffsverletzung.
Wie ist denn das "soll-Verhalten"? Wird sowas unterstützt?

stoxx 19. Mär 2009 11:28

Re: XML Serialisierer für beliebige DelphiObjecte auf RTTI B
 
müsste man mal überlegen, ob es sinnvoll wäre, in die Komponente zu integrieren, dass dieses Object automatisch erzeugt wird.
Das wird natürlich nicht gemacht bis jezt.
Object sollte in der Version schon created sein, gespeichert und geladen können bisher nur die genauen Werte der Published Properties ...
Auch von verlinkten Objekten ...


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:59 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