![]() |
TStrings und Assign
Hallo,
In TPersistent ist Assign so implementiert:
Delphi-Quellcode:
Ist es also nicht generell so gedacht dass AssignTo von den Nachfahren überschrieben wird?
procedure TPersistent.Assign(Source: TPersistent);
begin if Source <> nil then Source.AssignTo(Self) else AssignError(nil); end; So kann die Quelle entscheiden wie sie sich dem Zielobjekt zuweist. TStrings hat aber jetzt direkt Assign überschrieben und ruft inherited Assign quasi nicht mal auf (es sein denn Source wurde nicht von TStrings abgeleitet, aber das kommt wohl sowieso eher selten bis gar nicht vor). Jetzt stehe ich da mit meiner eigenen Ableitung von TStrings und möchte bestimmen wie eine TStringlist meine Klasse assignen soll und wollte dazu AssignTo überschreiben, aber das wird natürlich jetzt nie aufgerufen und ich hab verloren. Ist das wirklich so gewollt? In meinen Augen ist das ein Fehler.. |
AW: TStrings und Assign
Ich vermute mal, es ist by-design. Wenn eine von TPersistent abgeleitete Klasse keine eigene Implementierung von Assign hat, dann und nur dann wird die Source-Instanz über AssignTo mit der Zuweisung beauftragt. Da TStrings und seine Abkömmlingen aber ein eigenes Assign implementieren, ist AssignTo hier aus dem Rennen. Würde TStrings im Assign nach der Zuweisung noch inherited aufrufen, käme ja zusätzlich noch das AssignTo der Source-Instanz zum tragen und nicht alternativ.
Wenn du nun einen eigenen Abkömmling von TStrings schreibst, dann wirkt sich deine Implementierung von AssignTo allenfalls für Zielklassen aus, die nicht von TStrings abgeleitet sind und kein eigenes Assign bereitstellen, was deine Klasse berücksichtigt. Willst du eine spezielle Behandlung bei einer Zuweisung deiner Klasse nach TStringList, die von dem Standardverhalten abweicht, dann ist der bestehende Mechanismus von Assign einfach nicht der richtige Weg. Da wäre dann eine separate Methode á la AssignToStringList in deiner Klasse und ein Aufruf dieser an den entsprechenden Stellen wohl der bessere Weg. Vielleicht kannst du auch die Inheritance von TStrings aufbrechen, dann käme dein AssignTo wieder zum tragen. |
AW: TStrings und Assign
Ja gut, dass nicht ein implementiertes Assign UND das AssignTo aufgerufen werden (sollen) ist klar.
Ich bin nur davon ausgegangen dass das Überschreiben von AssignTo das Standardverfahren wäre. Ein AssignToStringlist bringt mir in meine Fall leider nichts weil mein Problem das Assign einer Stringliste im VCL-Code ist, den ich leider nicht grad auf AssignToStringlist umbauen kann :mrgreen: Naja dann muss ich mir irgendwie was schlaues überlegen :| |
AW: TStrings und Assign
Zitat:
Wenn ja, warum? Hört sich ein bisschen wie eine Verletzung des ![]() |
AW: TStrings und Assign
Das konkrete Problem ist:
Habe meine eigene Items-Klasse für meine Combobox (letztendlich von TStrings abgeleitet) und diese beinhaltet Werte die TStrings oder TStringlist nicht beinhaltet oder kennt. Beim erstellen der Combobox (CreateWnd, DestroyWnd) wird (aus welchen Gründen auch immer) eine Sicherheitskopie der Items in eine TStringlist (TCustomComboBox.FSaveItems) gespeichert (per Assign) wodurch meine zusätzlichen Infos natürlich nicht mit in diese TStringlist übertragen werden. Später wird diese Sicherung der Items wieder zurückgespielt und dadurch gehen die in meiner Items-Klasse enthaltenen zusätzlichen Informationen verloren. Da wollte ich mit einem überschriebenen AssignTo in meiner Items-Klasse den TStringlist-Fall abfangen und dafür sorgen dass die Daten mit rüberkommen. |
AW: TStrings und Assign
Dann wäre es vielleicht besser nicht von TStrings sonder von TList oder TObjectList abzuleiten?
|
AW: TStrings und Assign
Wo sind denn deine Zusatzdaten drin?
Wenn am TStrings.Objects, dann brauchst du nur dafür zu sorgen, daß die beiden TStrings-Nachfahren einen Speicherplatz für Objects beinhalten, denn das wird automatisch umkopiert, beim Assign. Nur haben nicht alle TStrings-Nachfahren sowas. (z.B. das TMemoStrings im TMemo) |
AW: TStrings und Assign
TPersistent.Assign bzw. TPersistent.AssignTo machen nichts außer Fehlermeldungen anzuzeigen. Weshalb es diese Implentierung überhaupt gibt hab ich noch nie verstanden? TStrings.Assign ruft TPersistent.Assign auf wenn Source <> TStrings ist. TStrings hat kein AssignTo. Deine Klasse braucht deshalb ein eigenes AssignTo oder mit TStrings.Assign arbeiten (falls möglich)?
|
AW: TStrings und Assign
Zitat:
|
AW: TStrings und Assign
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
![]() ![]() ![]() Dann kommt zum besseren Verständnis hier mal eine Preisfrage: Gegeben sind zwei Klassen in zwei getrennten Units:
Delphi-Quellcode:
und das entsprechende DatenTransferObjekt dazu
unit Model_Person;
interface uses Classes; type TPerson = class( TPersistent ) private FFirstname : string; FLastname : string; procedure AssignToPerson( Other : TPerson ); protected procedure AssignTo( Dest : TPersistent ); override; public constructor Create( const Firstname, Lastname : string ); published property Firstname : string read FFirstname; property Lastname : string read FLastname; end; implementation { TPerson } procedure TPerson.AssignTo( Dest : TPersistent ); begin if Dest is TPerson then AssignToPerson( Dest as TPerson ) else inherited; end; procedure TPerson.AssignToPerson( Other : TPerson ); begin Other.FFirstname := Self.FFirstname; Other.FLastname := Self.FLastname; end; constructor TPerson.Create( const Firstname, Lastname : string ); begin inherited Create; FFirstname := Firstname; FLastname := Lastname; end; end.
Delphi-Quellcode:
Nun wollen wir folgendes erreichen
unit DTO_Person;
interface uses Classes; type TPerson_DTO = class( TPersistent ) private FFirstname : string; FLastname : string; procedure AssignToPerson_DTO( Other : TPerson_DTO ); protected procedure AssignTo( Dest : TPersistent ); override; published property Firstname : string read FFirstname write FFirstname; property Lastname : string read FLastname write FLastname; end; implementation { TPerson_DTO } procedure TPerson_DTO.AssignTo( Dest : TPersistent ); begin if Dest is TPerson_DTO then AssignToPerson_DTO( Dest as TPerson_DTO ) else inherited; end; procedure TPerson_DTO.AssignToPerson_DTO( Other : TPerson_DTO ); begin Other.FFirstname := Self.FFirstname; Other.FLastname := Self.FLastname; end; end.
Delphi-Quellcode:
Wie muss nun die Implementierung aussehen (ohne beide Klassen in eine Unit zu packen)?
program dp_180780;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, Model_Person in 'Model_Person.pas', DTO_Person in 'DTO_Person.pas'; procedure Main; var LPerson_DTO : TPerson_DTO; LPerson : TPerson; begin LPerson := TPerson.Create( 'Peter', 'Lustig' ); try LPerson_DTO := TPerson_DTO.Create; try LPerson_DTO.Assign( LPerson ); LPerson_DTO.Firstname := 'Erwin'; LPerson.Assign( LPerson_DTO ); finally LPerson_DTO.Free; end; finally LPerson.Free; end; end; begin try Main; except on E : Exception do Writeln( E.ClassName, ': ', E.Message ); end; end. Auflösung Anhang 41354 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22: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