![]() |
Objekt kopieren... gibt es was Neues ?
Hallo alle...
Ich wollte 2 getrennte Objekte (Original / geändert) um evt. den Ursprungszustand wieder herstellen zu können und das geänderte für die Validitätsprüfung. Dabei bin ich der Hilfe von TPersistent ausgeliefert worden... :roll: Zitat:
Da die Beiträge alle samt aus den Jahren 2002 - 2008 etwa stammen drängte sich die Frage auf, ob mit den Neuen Delphi´s evt. neue Techniken eingeführt wurden um eine Objektkopie zu realisieren... Danke für Info´s |
AW: Objekt kopieren... gibt es was Neues ?
Naja mit Hilfe der RTTI lässt sich eigentlich immer was machen. Ab Delphi 2010 (?) sollte man auch die Public-Properties auslesen können glaube ich. (Du musst sie nicht mehr extra published machen).
|
AW: Objekt kopieren... gibt es was Neues ?
Danke für die schnelle Antwort... 8-)
Das mit der RTTI habe ich auch gelesen. Nur reichen mir die Public Properties nicht. Ich bräuchte eine vollständige Kopie. |
AW: Objekt kopieren... gibt es was Neues ?
Du könntest eventuell die dbExpress-Routinen benutzen, die auch DataSnap zum Marshalling/Unmarshalling verwendet. Ich fürchte aber, dass dir in der Professional die entsprechenden Units fehlen, da DataSnap erst in der Enterprise dabei ist.
Du kannst ja mal schauen, ob du die Units DBXJSON und DBXJSONReflect hast, dann sehen wir ggf. weiter. ;-) |
AW: Objekt kopieren... gibt es was Neues ?
Liste der Anhänge anzeigen (Anzahl: 1)
...die wären schon mal da.
|
AW: Objekt kopieren... gibt es was Neues ?
Dann findest du im SVN hier eine passende Demo, das Repository kannst du einfach mit Delphi öffnen:
![]() ![]() (Außerdem hast du die Demo dann vermutlich auch schon lokal in den Samples.) Für dich interessant sind die Knöpfe zum Marshalling und Unmarshalling. ;-) |
AW: Objekt kopieren... gibt es was Neues ?
Zitat:
|
AW: Objekt kopieren... gibt es was Neues ?
Selbst "private" Dinge lassen sich mit der neuen RTTI standardmäßig auslesen (ja, es gibt einen Grund, warum die EXEn so groß geworden sind :roll: )
[edit] Da war zwar wer schneller, aber egal. :angle2: [/edit] Aber beim Kopieren muß man aufpassen, denn vorallen wenn Pointer und Handle im Spiel sind (noch schlimmer, wenn gecastete Pointer und Handle z.B. als Integer vorkommen) oder irgendwelche Indize auf eindeutige externe Strukturen (z.B. die ID einer Hardware- oder Datenbankverbindung), dann kann man ohne Kenntnisse des Aufbaus und der Funktion dieses Objektes eigentlich nichts kopieren, ohne irgendwas kaputtzumachen. Aus diesem Grund sollte man vorallem vor den Interna (private/protected) eher Abstand nehmen. |
AW: Objekt kopieren... gibt es was Neues ?
Diese Lösung ist sehr kompakt, erfordert nur Delphi 2010 und keine weiteren Bibliotheken:
![]() Sie verwendet die neuen JSON Klassen in Delphi um das Objekt erst zu serialisieren und dann wieder in ein neues zu deserialisieren. |
AW: Objekt kopieren... gibt es was Neues ?
Genau die Lösung wird ja in der Demo oben verwendet...
|
AW: Objekt kopieren... gibt es was Neues ?
Sooo...
Hab die Demo mal am laufen. Wenn ich das richtig verstehe zerpfückt Marshall das Object in JSON "Text" incl. Daten. Das Unmarshall setzt aus diesem "Text" ein Object zusammen und gibt es zurück. Leider bekomme ich beim Unmarshall mit TPerson1 eine Zugriffsverletztung. Die Listen gehen. Die Richtung stimmt schon mal oder ? |
AW: Objekt kopieren... gibt es was Neues ?
Ja, das stimmt so. Bei XE gibt es aber noch einen Fehler, der dazu führt, dass Dezimalzahlen nicht korrekt übertragen werden. Leider wird nämlich der lokale Dezimalseparator benutzt und der stimmt nun einmal in Deutschland mit dem Feldtrennzeichen von JSON überein. Ich glaube daher rührt der Fehler.
Deshalb musst du bei XE vor dem Marshalling/Unmarshalling den Dezimalseparator auf einen Punkt setzen und danach wieder zurück. Bei XE2 ist das behoben. |
AW: Objekt kopieren... gibt es was Neues ?
Wenn man aber lokal kopiert, dann sollte das doch egal sein? (wenn beim Unmarshallen der selbe "lokale" Separator verwendet wird, wie beim Marshallen)
Schau dir mal den JSON-String an, also ob dort auch alles drin ist, was rein müßte. |
AW: Objekt kopieren... gibt es was Neues ?
8-) Du traust mir echt zu, daß ich das verstehe ?
Zitat:
Zitat:
|
AW: Objekt kopieren... gibt es was Neues ?
Code:
[...] = ein Array, bzw. eine Liste
{
"type": "Person1.TPerson1", "id": 1, "fields": { "FFirstName": "aSampleFirst", "FLastName": "aSampleLast", "FWeightLb": 160, "FHeightIn": 70, 5, "FDateOfBirth": 22261, "FAddresses": [ [ "addHome", "aSampleHomeStreet", "aSampleHomeCity", "aSampleHomeState", "aSampleHomeZip" ], [ "addWork", "aSampleWorkStreet", "aSampleWorkCity", "aSampleWorkState", "aSampleWorkZip" ] ], "FPhones": [ [ "aSampleMobileNumber", "phMobile" ], [ "aSampleWorkNumber", "phWork" ], [ "aSampleHomeNumber", "phHome" ] ] } } {...} = ein Objekt x:y = ein Parameter (Name:Wert) Nur mit dieser namenlosen
Delphi-Quellcode:
kann ich nicht viel anfangen.
5,
Ich weiß jetzt nicht wie das Objekt aussieht (hab hier in keine Anhänge reingesehn), aber Listen scheinen schon drin zu sein. (k.A. ob auch alles richtig ist) Dezimalzahlen sind hier nicht enthalten, also sollte es damit keine Probleme geben, oder soll das Eine eine 70,5 sein? |
AW: Objekt kopieren... gibt es was Neues ?
Zitat:
in der MainUnit(Form.Create) waren Kommentare bezüglich der Testung alternativer Dezimalseperatoren. Dort habe ich den Dezimalseperator auf "." umgestellt und im OnDestroy wieder zurück. Damit geht auch TPerson1. Jetzt muß ich mal schauen was ich alles wo benötige. (TTypeFactory etc.) Am besten ich mache mir mal ein Testprogramm und gehe Euch dann auf die Nerven... 8-) Nachtrag: Zitat:
PS: ist der auf einem deutschen System nicht normal sowieso der "." :gruebel: |
AW: Objekt kopieren... gibt es was Neues ?
unter XE bekomme ich
"Exception der Klasse EInsufficientRtti mit der Meldung 'Unzureichende RTTI zur Unterstützung dieser Operation verfügbar'" bei :
Delphi-Quellcode:
With Button2.Clone do
begin left := left + 100; top := top + 100; end; |
AW: Objekt kopieren... gibt es was Neues ?
...bei der gleichen Demo ? Hast du die aktuelle Version aus dem Repository ?
|
AW: Objekt kopieren... gibt es was Neues ?
Nicht systemweit (Windows), sondern nur programmweit (in deinem Programm).
PS: Beim Button (allem ab TComponent, wenn ordentlich programmiert), kannst du auch TStream verwenden. ![]() |
AW: Objekt kopieren... gibt es was Neues ?
...ja dann ist es gut. 8-)
|
AW: Objekt kopieren... gibt es was Neues ?
Zitat:
Zum Auslesen müßtest du aber die Komponente erstemal erstellen und dann mit den StreamDaten befüllen. Vollen Klassennamen merken und dann kann man über die RTTI die Typdeklaration der Klasse suchen und darüber erstellen lassen. Ich glaub daheim hab ich noch irgendwo etwas dafür- |
AW: Objekt kopieren... gibt es was Neues ?
Danke erstmal... 8-)
Bei meinen Anforderungen handelt es sich ausschließlich um eigene "Daten"-Objekte. Nachtrag: Ich hatte diverse Beiträge auf Seite 1 übersehen. Vor allem der Link in Beitrag 9 ![]() Danke an alle. Wenn das, so wie verlautet, auch mit generischen Listen im Objekt funktioniert, wäre das "Muster" gut geeignet für die CodeLib... Nachtrag Lösung: habe jetzt nach folgendem Muster umgestellt...
Delphi-Quellcode:
Verwendung...
.....
uses DBXJSON, DBXJSONReflect; ..... function DeepCopy(aValue: TObject): TObject; var MarshalObj: TJSONMarshal; UnMarshalObj: TJSONUnMarshal; JSONValue: TJSONValue; begin Result:= nil; MarshalObj := TJSONMarshal.Create; UnMarshalObj := TJSONUnMarshal.Create; try JSONValue := MarshalObj.Marshal(aValue); try if Assigned(JSONValue) then Result:= UnMarshalObj.Unmarshal(JSONValue); finally JSONValue.Free; end; finally MarshalObj.Free; UnMarshalObj.Free; end; end;
Delphi-Quellcode:
Die Verwendung als ClassHelper ist auch sehr interessant. (Siehe Link)
.....
var MyObject1, MyObject2: TMyObject; begin //Regular object construction MyObject1:= TMyObject.Create; //Deep copying an object MyObject2:= TMyObject(DeepCopy(MyObject1)); try //Do something here finally MyObject1.Free; MyObject2.Free; end; end; Erste Tests sind gut. Wollen wir dann mal schauen wie das mit "Unterobjekten" und generischen Listen funktioniert. Danke an alle...:hi: |
AW: Objekt kopieren... gibt es was Neues ?
Ich habe (unter XE) eine eigene Funktion geschrieben, die bestimmte Objekteigenschaften direkt an ein anderes Objekt zuweist.
Die betreffenden Eigenschaften sind mit einem Attribut gekennzeichnet. Die Objekte (Tod) haben eine gemeinsame Basis. Die Ableitungen (Todl) verwalten zusätzlich eine Liste von Tod-Objekten. Falls jemand eine Anregung daraus übernehmen will, hier der Quelltext:
Delphi-Quellcode:
TodCourt = class(TodCustomStahliSport)
... public constructor Create(AOwner: TComponent); override; destructor Destroy; override; function IsFree: Boolean; [AttrOd] // <- Kennzeichnung zum Kopieren property Number: Integer read get_Number write set_Number; [AttrOd] property CourtType: TCourtType read get_CourtType write set_CourtType; [AttrOd] property Activate: Boolean read get_Activate write set_Activate; [AttrOd] property Game: TodGame read get_Game write set_Game; [AttrOd] property PositionValues: String read get_PositionValues write set_PositionValues; published end; // procedure TodProp.AssignFromTo(odFrom, odTo: Tod); var ContextFrom: TRttiContext; ContextTo: TRttiContext; RttiTypeFrom: TRttiType; RttiTypeTo: TRttiType; PropInfoFrom: TRttiProperty; PropInfoTo: TRttiProperty; FFrom: Boolean; FTo: Boolean; AttrFrom: TCustomAttribute; AttrTo: TCustomAttribute; ValueFrom: TValue; ValueTo: TValue; _oFrom, _oTo: TObject; _odFrom, _odTo: Tod; odlFrom: Todl; odlTo: Todl; begin if (not Assigned(odFrom)) or (not Assigned(odTo)) then Exit; ContextFrom := TRttiContext.Create; RttiTypeFrom := ContextFrom.GetType(odFrom.ClassType); ContextTo := TRttiContext.Create; RttiTypeTo := ContextTo.GetType(odTo.ClassType); if (Assigned(RttiTypeFrom)) and (Assigned(RttiTypeTo)) then begin for PropInfoFrom in RttiTypeFrom.GetProperties do begin FFrom := False; for AttrFrom in PropInfoFrom.GetAttributes do begin if AttrFrom is AttrOd then FFrom := True; end; if FFrom then begin for PropInfoTo in RttiTypeTo.GetProperties do begin FTo := False; for AttrTo in PropInfoTo.GetAttributes do begin if AttrTo is AttrOd then FTo := True; end; if FTo then begin if PropInfoFrom.PropertyType = PropInfoTo.PropertyType then begin ValueFrom := PropInfoFrom.GetValue(odFrom); if PropInfoTo.IsWritable then begin PropInfoTo.SetValue(odTo, ValueFrom); end else begin _oFrom := ValueFrom.AsObject; if _oFrom is Tod then _odFrom := (_oFrom as Tod) else _odFrom := nil; ValueTo := PropInfoTo.GetValue(odFrom); _oTo := ValueTo.AsObject; if _oTo is Tod then _odTo := (_oTo as Tod) else _odTo := nil; if Assigned(_odTo) then begin if Assigned(_odFrom) then _odTo.Assign(odFrom) else _odTo.Clear; end; end; end; end; end; end; end; end; ContextFrom.Free; ContextTo.Free; if (odFrom is Todl) and (odTo is Todl) then begin odlFrom := (odFrom as Todl); odlTo := (odTo as Todl); // outputdebugstring(pchar('a:' + inttostr(odlFrom.Items.Count))); // outputdebugstring(pchar('b:' + inttostr(odlTo.Items.Count))); odlTo.Items.Assign(odlFrom.Items); // outputdebugstring(pchar('c:' + inttostr(odlFrom.Items.Count))); // outputdebugstring(pchar('d:' + inttostr(odlTo.Items.Count))); end; end; @haentschman Mit generischen Klassen sollte eine solche Serialisierung auch funktionieren. Man kann lediglich nicht eine generische Klasse von einer anderen ableiten und diese Ableitung später nachvollziehen (sofern ich das so richtig zusammenfasse). |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:51 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