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:
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;
Die Listenklasse dazu sieht bis jetzt so aus (fehlt noch die Hälfte)...
Delphi-Quellcode:
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;
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)
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.
Viele Grüße,
Schorsch