AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Listenklasse für beliebige Datenklassen (RTTI)
Thema durchsuchen
Ansicht
Themen-Optionen

Listenklasse für beliebige Datenklassen (RTTI)

Ein Thema von Schorschi5566 · begonnen am 23. Apr 2010 · letzter Beitrag vom 24. Apr 2010
Antwort Antwort
Schorschi5566

Registriert seit: 6. Feb 2006
197 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#1

Listenklasse für beliebige Datenklassen (RTTI)

  Alt 23. Apr 2010, 22:12
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
Uwe
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#2

Re: Listenklasse für beliebige Datenklassen (RTTI)

  Alt 24. Apr 2010, 08:40
Das Problem ist mit RTTI nicht lösbar.
Michael Justin
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#3

Re: Listenklasse für beliebige Datenklassen (RTTI)

  Alt 24. Apr 2010, 10:25
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;
Uwe Raabe
  Mit Zitat antworten Zitat
Schorschi5566

Registriert seit: 6. Feb 2006
197 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#4

Re: Listenklasse für beliebige Datenklassen (RTTI)

  Alt 24. Apr 2010, 20:41
Hallo zusammen,

danke für Eure Antworten.

@Uwe:

Zitat von Uwe:
Warum nicht gleich eine generische Liste? TObjectList<T>
Weil ich die Sache mit <T> schlicht nicht kannte. Aber danke für den Hinweis.

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.


Viele Grüße,
Schorsch
Uwe
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:51 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