Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi RTTI - Properties setzen (https://www.delphipraxis.net/87351-rtti-properties-setzen.html)

GuenterS 27. Feb 2007 14:39


RTTI - Properties setzen
 
Hallo.

Wie ich mit GetPropList die namen der verfügbaren Properties bekomme weiß ich, aber wie könnte ich aufgrund dem dort gefundenen Namen, dieses Propertie eines bestimmten Objektes setzen?

DGL-luke 27. Feb 2007 15:18

Re: RTTI - Properties setzen
 
Iie Funktion heißt ganz banal Delphi-Referenz durchsuchenTypInfo.SetObjectProp.

GuenterS 27. Feb 2007 15:35

Re: RTTI - Properties setzen
 
Dankeschön,
und wenn ich einen Integer und kein Object setzen möchte dann nehm ich SetOrdProp usw.


aber wie gehe ich mit einem TDateTime Property um?

shmia 27. Feb 2007 16:26

Re: RTTI - Properties setzen
 
Zitat:

Zitat von GuenterS
aber wie gehe ich mit einem TDateTime Property um?

TDateTime ist intern ein Double. Also SetFloatValue

GuenterS 27. Feb 2007 16:28

Re: RTTI - Properties setzen
 
Danke das war mir schon klar, aber wie unterscheidet man dann Float Werte von TDateTime Werte?

Das ist sehr interessant, wenn man versucht eine Datenbank zu befüllen und man Datum und FloatFelder hat.

shmia 27. Feb 2007 16:35

Re: RTTI - Properties setzen
 
Zitat:

Zitat von GuenterS
... aber wie unterscheidet man dann Float Werte von TDateTime Werte?

Über den "PropTypeName":
Delphi-Quellcode:
var
   PropInfos: PPropList;
   PropTypeName : string;
   pi : PPropInfo;
begin
...
      GetPropList(obj.ClassInfo, type_kinds, PropInfos);
...

      for i := 0 to prop_count - 1 do
      begin
         s := '';

         pi := PropInfos^[i];
         PropTypeName := pi.PropType^.Name;
         if PropTypeName='TDateTime' then
            ...

GuenterS 27. Feb 2007 17:46

Re: RTTI - Properties setzen
 
Super, danke das funktioniert :)

shmia 27. Feb 2007 17:49

Re: RTTI - Properties setzen
 
Was hast du denn vor ?
Etwa published Properties in ein Dataset schreiben und lesen?
(das hab ich hier schon fertig in der Schublade :mrgreen: )

GuenterS 27. Feb 2007 17:59

Re: RTTI - Properties setzen
 
Genau das, habe ich vor...

Wobei ich das Dataset aber auslass und direkt ein Insert bzw. Update Statement absetzen will.

GuenterS 10. Apr 2007 16:04

Re: RTTI - Properties setzen
 
Unter einer Applikation funktioniert das mit dem RTTI schon ganz gut, leider scheint es unter einem Service nicht ganz so tolle funktionieren.

Ist darüber schon etwas bekannt?

Gruber_Hans_12345 10. Apr 2007 16:12

Re: RTTI - Properties setzen
 
hmmm, kann mir nicht vorstellen, das es bei services anders sein sollte, da es reine delphi interne sache ist

Von welchem Objekt ist die Klasse abgeleitet?
Eventuell die compilerdirective {$M+} vor der ersten deklaration der klasse geben, damit auch die RTTI von der klasse reincompiliert wird (oder eben von TPersitant ableiten)

GuenterS 10. Apr 2007 16:36

Re: RTTI - Properties setzen
 
Das mit dem Service war mein Fehler, hat damit eigentlich nichts zu tun, tritt genauso in der Applikation auf.

Konnte jetzt aber folgendes Phänomen beobachten.

Ich habe eine Klassenhirarchie die folgendermassen aussieht:
Delphi-Quellcode:
TBaseClass = class of TBasis;

TBasis = class(TObject)

TMitarbeiter = class(TBasis)
published
   property Name: string read FName write FName;
end;

TChef = class(TBasis)
published
   property Titel: string read FTitel write FTitel;
end;
all diese Klassen sind unter der Compilerdirektive {$M+} definiert (im SourceCode natürlich vollständiger).

Jetzt habe ich eine Prozedur in welcher eine Klassenname übergeben wird, aus welcher die entsprechenden Properties ausgelesen werden sollen. Diese schaut (gekürzt) folgendermassen aus:
Delphi-Quellcode:
procedure Synchronize(aClass: TBaseClass);
var
  lBasisClass: TBasis;
  lPropList: TPropList;
  i: integer;
begin
  lBasisClass := aClass.Create;

  GetPropList(lBasisClass.ClassInfo, tkProperties, @lPropList);

  i := 0;
  while ((lPropList[i] <> nil) and (i < high(lPropList))) do
  begin
    //Properties entsprechend setzen
     case PropType(lBasisClass , lPropList[i].Name) of
       tkInteger:
         SetOrdProp(lBasisClass , lPropList[i].Name, lQry.FieldByName(lPropList[i].Name).AsInteger);
       tkFloat:
         SetFloatProp(lBasisClass , lPropList[i].Name, lQry.FieldByName(lPropList[i].Name).AsFloat);
       tkString, tkLString:
         SetStrProp(lBasisClass , lPropList[i].Name, lQry.FieldByName(lPropList[i].Name).AsString);
     end;
     inc(i);
  end;
  lBasisClass.Free;
end;
Wenn ich diese Prozedur mit dem Parameter TMitarbeiter aufruf klappt alles. Beende ich das Programm und rufe die Prozedur mit Paramter TChef auf klappt auch alles. Rufe ich aber zuerst TMitarbeiter und dann TChef auf, ohne dazwischen das Programm zu beenden, findet er die Properties von TMitarbeiter. Dies funktioniert auch andersrum so.

Was könnte ich tun?

shmia 10. Apr 2007 16:53

Re: RTTI - Properties setzen
 
Mach mal den Konstruktor von TBasis virtuell.
Andernfalls wird bei lBasisClass := aClass.Create nicht der richtige Konstruktor aufgerufen.
Vergleiche das mal mit TComponent.Create. (Ab TComponent ist der Konstruktor virtuell)

GuenterS 10. Apr 2007 17:02

Re: RTTI - Properties setzen
 
Das habe ich gemacht, allerdings ohne einen Erfolg zu erzielen. Die abgeleiteten Klassen haben allerdings keinen eigenen Konstruktor.

[Idee]
Diese Liste was ich da bekomme, ich vermute, dass die einfach nicht geleert wird durch das Holen der neuen Werte? Teste dies eben mal...
[/Idee]

shmia 10. Apr 2007 17:15

Re: RTTI - Properties setzen
 
Zitat:

Zitat von GuenterS
das habe ich gemacht, allerdings ohne einen Erfolg zu erzielen.

War aber auch kein Fehler. Jetzt kannst du zunächst mal jeweils einen Konstruktor für TChef und TMitarbeiter schreiben und die Properties dort mal vorbelegen.
Delphi-Quellcode:
constructor TChef.Create; {override}
begin
   inherited;
   Titel := 'Oberboss, Stressmacher';
end;
Dann so weiter debuggen:
Delphi-Quellcode:
procedure Synchronize(aClass: TBaseClass);
var
  lBasisClass: TBasis;
  lPropList: TPropList;
  i: integer;
begin
  lBasisClass := aClass.Create;
  ShowMessage('lBasisClass =Class('+lBasisClass.Classname+')'); // Klassenname anzeigen
Mit der Anzeige von Classname kannst du überprüfen, ob auch das erzeugt Objekt auch wirklich
zu der gewünschten Klasse gehört.

GuenterS 10. Apr 2007 17:18

Re: RTTI - Properties setzen
 
der Classname als auch ClassType selber stimmt auch, ganz am anfang der Liste kommen die richtigen Properties, danach die falschen.

shmia 10. Apr 2007 17:29

Re: RTTI - Properties setzen
 
Zitat:

Zitat von GuenterS
ganz am anfang der Liste kommen die richtigen Properties, danach die falschen.

Ahhhhrrrrrrg!! :freak:
GetPropList() liefert die Anzahl der Properties zurück. Deine While-Schleife ist falsch.
Hier ist eine For-Schleife angebracht:
Delphi-Quellcode:
  prop_count := GetPropList(obj.ClassInfo, type_kinds, nil);
....
  for i := 0 to prop_count - 1 do

GuenterS 10. Apr 2007 17:33

Re: RTTI - Properties setzen
 
danke :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:54 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