![]() |
Listenklasse für beliebige Datenklassen (RTTI)
Hallo liebe DPler,
seit kurzem habe ich nun auch Delphi 2010 und wollte natürlich mal was mit den neuen Features machen. Es geht um eine Listenklasse, der man von außen eine Datenklasse übergibt ohne dass sie diese kennen würde. Sollte man ja mit RTTI was machen können. :) Eine Anforderung ist, dass ich nicht ständig irgendwo casten möchte. Das Handling soll etwa so aussehen:
Delphi-Quellcode:
Die Listenklasse dazu sieht bis jetzt so aus (fehlt noch die Hälfte)...
type
TDataObject = class(TPersistent) public MeinString, DeinString: String; MeinInteger: Word; end; . . . procedure TForm1.Button1Click(Sender: TObject); var List: TUniList; DataInterface, Data: TDataObject; begin DataInterface := TDataObject.Create; List := TUniList.Create(DataInterface); Data := TDataObject.Create; Data.MeinString := 'Anfang'; Data.MeinInteger := 200; List.Add(Data); Data.MeinString := 'Ende'; Data.MeinInteger := 100; List.Add(Data); List.First; showmessage(DataInterface.MeinString + ' ' + IntToStr (DataInterface.MeinInteger)); // Hier kommt "Anfang 200" List.Last; showmessage(DataInterface.MeinString + ' ' + IntToStr (DataInterface.MeinInteger)); // Hier kommt "Ende 100" List.Free; Data.Free; end;
Delphi-Quellcode:
Die Sache mit dem DataInterface habe ich gemacht, weil es mir bisher nicht gelungen ist innerhalb der Listenklasse ein Objekt vom Typ TDataObject zu generieren und auch zurückgeben zu können. (Generieren schon, siehe TUniList.Add aber eben nicht zurückgeben)
TUniList = class(TObject)
FData: TObjectList; FObj: TObject; // das Interface nach draussen FClass: TClass; procedure AssignTo(Item: TObject); public constructor Create(DataInterface: TObject); destructor Destroy; procedure Add(Item: TObject); procedure First; procedure Last; end; . . . procedure TUniList.Add(Item: TObject); var Obj: TObject; context: TRttiContext; typinfo: TRttiType; field: TRttiField; begin // Object an Liste anhängen Obj := FClass.NewInstance; // neue Instanz von der Containerklasse erzeugen context := TRttiContext.Create; typinfo := context.GetType(FClass); for field in typinfo.GetFields do begin field.SetValue(Obj, field.GetValue(Item)); end; FData.Add(Obj); context.Free; end; procedure TUniList.AssignTo(Item: TObject); var context: TRttiContext; typinfo: TRttiType; field: TRttiField; begin context := TRttiContext.Create; typinfo := context.GetType(FClass); for field in typinfo.GetFields do begin field.SetValue(FObj, field.GetValue(Item)); end; context.Free; end; constructor TUniList.Create(DataInterface: TObject); begin FData := TObjectList.Create; FClass := DataInterface.ClassType; FObj := DataInterface; end; destructor TUniList.Destroy; begin FData.Free; FObj.Free; // wird hier richtig frei gegeben oder gibt's ein Speicherleck? end; procedure TUniList.First; var Obj: TObject; begin Obj := FData.First; AssignTo(Obj); // Werte aus Liste in DataInterface schreiben end; procedure TUniList.Last; var Obj: TObject; begin Obj := FData.Last; AssignTo(Obj); // Werte aus Liste in DataInterface schreiben end; Kann man mit RTTI auch zur Laufzeit den Rückgabewert einer function beeinflussen? Wäre nett, wenn sich das mal einer der Cracks ansehen könnte und mir sagt ob das so passt oder völlig daneben ist oder viel einfacher geht. :P Viele Grüße, Schorsch |
Re: Listenklasse für beliebige Datenklassen (RTTI)
Das Problem ist mit RTTI nicht lösbar.
|
Re: Listenklasse für beliebige Datenklassen (RTTI)
Warum nicht gleich eine generische Liste? TObjectList<T> kümmert sich auch automatisch um die Freigabe der enthaltenen Objekte.
Delphi-Quellcode:
uses
Generics.Collection; type TDataObject = class(TPersistent) public MeinString, DeinString: String; MeinInteger: Word; end; procedure TForm1.Button1Click(Sender: TObject); var List: TObjectList<TDataObject>; Data: TDataObject; begin List := TObjectList<TDataObject>.Create; try Data := TDataObject.Create; Data.MeinString := 'Anfang'; Data.MeinInteger := 200; List.Add(Data); Data.MeinString := 'Ende'; Data.MeinInteger := 100; List.Add(Data); Data := List.First; showmessage(Data.MeinString + ' ' + IntToStr (Data.MeinInteger)); // Hier kommt "Anfang 200" Data := List.Last; showmessage(Data.MeinString + ' ' + IntToStr (Data.MeinInteger)); // Hier kommt "Ende 100" finally List.Free; end; end; |
Re: Listenklasse für beliebige Datenklassen (RTTI)
Hallo zusammen,
danke für Eure Antworten. @Uwe: Zitat:
Würde das denn auch mit einer von TObjectList abgeleiteten und erweiterten Listenklasse funktionieren? Wie würden dann beispielsweise die Funktionen Next und Prev das aktuelle Listenobjekt zurückgeben ohne von der Datenklasse zu wissen? Ich habe mal mit meinem Ansatz weitergemacht und IndexOf(Field, Value) und Sort(Field) mit RTTI implementiert. Das finde ich schon sehr schnucklig. Eine Funktion kümmert sich um alle Felder. Wenn sowas jetzt auch mit generischen Listen geht, gehen mir langsam die Ideen aus, wie man RTTI sinnvoll einsetzen kann. :mrgreen: Viele Grüße, Schorsch |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:00 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