Autor Beitrag
ProggyPeter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 33



BeitragVerfasst: Mi 18.04.12 09:22 
Hallo,
mit Rtti habe ich mich erst wenig beschäftigt.
Deshalb wäre ich dankbar, wenn ein paar Tips/Codezeilen zur Lösung beitragen könnten.

Ich möchte eine Datenklasse definieren.
Aus dieser Klasse möchte ich zur Laufzeit Variablenname und Variablentyp auslesen.
Die Datenklasse hat die gleiche Struktur und Feldnamen wie ein zugehöriger Datenbankrecord.

Beispiel:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
type
  TDataClass = class
   KID: Integer;
   Name: string;
   Vorname: string;
   ADRID: integer;
 end;


Zur Laufzeit möchte ich diese Datenklasse aus einer Query füllen.

ausblenden Delphi-Quelltext
1:
GetData('SELECT * FROM TESTDAT WHERE KID=123' , DataClass);					



Für einen Tip dankbar.

Mit Gruß
Peter


Moderiert von user profile iconNarses: Topic aus Sonstiges (Delphi) verschoben am Mi 18.04.2012 um 10:02
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Mi 18.04.12 11:35 
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
unit Unit2;
// DemoRumpf für RTTI - Setter, Thomas Wassermann 2012
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,TypINfo,rtti;

type
  TDataClass = class
   FKID: Integer;
   FName: string;
   FVorname: string;
   FADRID: integer;
   published
   Property KID: Integer read FKID write FKID;
   Property Name: string read FName write FName;
   Property Vorname: string read FVorname write FVorname;
   Property ADRID: Integer read FADRID write FADRID;
 end;
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
   d:TDataClass;
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}



Procedure SetValue(obj:TObject;aName:String;AValue:Variant);
var
   PropInfos: TPropList;
   PropTypeName : string;
   pi : PPropInfo;
   i:Integer;
begin
      for i := 0 to GetPropList(obj.ClassInfo, tkProperties, @PropInfos) - 1 do
      begin
         if PropInfos[i].Name = aName then
            begin
               case PropType(obj , PropInfos[i].Name) of
                 tkInteger:
                   SetOrdProp(obj , PropInfos[i].Name, AValue);
                 tkFloat:
                   SetFloatProp(obj , PropInfos[i].Name, AValue);
                 tkString, tkLString,tkUString:
                   SetStrProp(obj , PropInfos[i].Name, AValue);
               end;
            end;

      end;
end;

procedure TForm2.Button1Click(Sender: TObject);
var
 d:TDataClass;
begin
  d:=TDataClass.Create;
  SetValue(d,'Name','Test');
  SetValue(d,'KID',1234);
  Showmessage(d.Name + #13#10 + IntToStr(d.KID) );
  d.Free;
end;

end.

_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS
ProggyPeter Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 33



BeitragVerfasst: Mi 18.04.12 14:02 
Erst mal Danke für den Tip.
Mit propertys wollte ich eigentlich nicht arbeiten.
Ich habe zwischenzeitlich weiter probiert und habe diese Lösung
angewendet.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
var
  Obj: TObject;
  context: TRttiContext;
  typinfo: TRttiType;
  field: TRttiField;
  s : string;
begin
  lst1.Items.Clear;
  context := TRttiContext.Create;
  typinfo := context.GetType(Data.ClassInfo);
  for field in typinfo.GetFields do
  begin
    typinfo := field.FieldType;
    s := '';
    if typinfo <> nil then
      s := typinfo.Name;
           lst1.Items.Add(field.Name + '  ' + s );
   end;
  context.Free
end;



Mit
if UpperCase(field.Name) = 'BEZEICHNUNG' then
l := field.GetValue(Data).AsString;

kann ich den Inhalt der Variablen auslesen. Das funktioniert auch.
Was ich noch suche ist die Gegenrichtung.
Also

if UpperCase(field.Name) = 'BEZEICHNUNG' then
field.SetValue(Data , Value);

Hier habe ich noch ein Problem mit dem Handling von TValue;

Gruß
Peter
ProggyPeter Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 33



BeitragVerfasst: Do 19.04.12 09:25 
So jetzt habe ich den zweiten Teil auch gelöst.
Für alle, die es interessiert nachfolgend die Realisierung.

Ziel war es, eine komplette Datenklasse aus einer Firebird-Datenbank zu füllen.
Vielen Dank nochmals für die freundliche Unterstützung.

MfG
Peter

Die Anwendung

ausblenden Delphi-Quelltext
1:
if DataSQL.Select('KOMBINIERT', Data, ['KID=',9003]) then ...					


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
procedure TIBDacSQL.FieldstoInstance(Fields: TFields; Instance: TObject);
var
  context: TRttiContext;
  typinfo: TRttiType;
  field: TRttiField;
  n : Integer;
  s : string;
  va: TValue;
begin
  n := 0;
  context := TRttiContext.Create;
  typinfo := context.GetType(Instance.ClassInfo);

  for field in typinfo.GetFields do
  begin
    Va := Field.GetValue(Instance);
    case va.Kind of
      tkInteger: field.SetValue(Instance,Fields[n].AsInteger );
      tkInt64  : field.SetValue(Instance,Fields[n].AsLargeInt);
      tkFloat  : field.SetValue(Instance,Fields[n].AsFloat);
      tkChar   : field.SetValue(Instance,Fields[n].AsString);
      tkWChar  : field.SetValue(Instance,AnsiChar(Fields[n].AsBytes));
      tkUString: field.SetValue(Instance,Fields[n].AsString);
      tkString,
      tkLString,
      tkWString : field.SetValue(Instance,AnsiString(Fields[n].AsString));
    end;
    inc(n);
  end;
end;