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: GetPropValue(TTimeSpan) (https://www.delphipraxis.net/201155-rtti-getpropvalue-ttimespan.html)

hzzm 27. Jun 2019 10:58

Delphi-Version: 10 Seattle

RTTI: GetPropValue(TTimeSpan)
 
Guten Tag,

ich habe gerade das Problem, dass ich in TypInfo/RTTI den Wert von einer TTimeSpan so holen muesste
Delphi-Quellcode:
function RetrieveValue(AConcreteItem: TPersistent; APropIndex: Integer): Variant;
var
  LPropCount: Integer;
  LPropList: PPropList;
  LType: TClass;
begin
  LType := AConcreteItem.ClassType;
  LPropCount := GetTypeData(LType.ClassInfo)^.PropCount;
  GetMem(LPropList, LPropCount * SizeOf(Pointer));
  GetPropInfos(LType.ClassInfo, LPropList);
  if LPropList[APropIndex].PropType^.Name = 'TTimeSpan' then
    Result := GetStrProp(AConcreteItem, LPropList[APropIndex]) // <<-- Result = ''
  else
    Result := GetPropValue(AConcreteItem, LPropList[APropIndex], False);
end;
So geht das natuerlich nicht. TTimeSpan ist ein Record, darauf ist GetPropValue nicht vorbereitet.
Ich muesste eigentlich eine Ebene tiefer in GetPropValue einen cast
Delphi-Quellcode:
String(TTimeSpan)
durchfuehren, dann waere alles OK.

Wie kann ich das elegant beheben?

peterbelow 27. Jun 2019 11:40

AW: RTTI: GetPropValue(TTimeSpan)
 
Zitat:

Zitat von hzzm (Beitrag 1435476)
Guten Tag,

ich habe gerade das Problem, dass ich in TypInfo/RTTI den Wert von einer TTimeSpan so holen muesste
Delphi-Quellcode:
function RetrieveValue(AConcreteItem: TPersistent; APropIndex: Integer): Variant;
var
  LPropCount: Integer;
  LPropList: PPropList;
  LType: TClass;
begin
  LType := AConcreteItem.ClassType;
  LPropCount := GetTypeData(LType.ClassInfo)^.PropCount;
  GetMem(LPropList, LPropCount * SizeOf(Pointer));
  GetPropInfos(LType.ClassInfo, LPropList);
  if LPropList[APropIndex].PropType^.Name = 'TTimeSpan' then
    Result := GetStrProp(AConcreteItem, LPropList[APropIndex]) // <<-- Result = ''
  else
    Result := GetPropValue(AConcreteItem, LPropList[APropIndex], False);
end;
So geht das natuerlich nicht. TTimeSpan ist ein Record, darauf ist GetPropValue nicht vorbereitet.
Ich muesste eigentlich eine Ebene tiefer in GetPropValue einen cast
Delphi-Quellcode:
String(TTimeSpan)
durchfuehren, dann waere alles OK.

Wie kann ich das elegant beheben?

Sie Dir mal in System.Typinfo.pas den Typ TPropSet<T> an (ich hoffe Seattle hatte den schon). Leider ist er nur innerhalb der Implementierung der Unit sichtbar, aber wie er GetProc implementiert sollte Dir ein paar Hinweise auf eine mögliche Lösung für dein Problem geben.

Stevie 27. Jun 2019 12:00

AW: RTTI: GetPropValue(TTimeSpan)
 
TTimeSpan hat ja nur ein Feld des Typs Int64, also sollte technisch möglich sein, hier GetInt64Prop aufzurufen, aber das geht dann nur deshalb, weil TTimeSpan dasselbe Layout wie ein Int64 hat, für keine anderen Records (*). Dann hast du aber den Wert aus dem FTicks Feld in deinem Variant.

Übrigens, bitte keine Typüberprüfung per Namen - besser ist es so:

Delphi-Quellcode:
if LPropList[APropIndex].PropType^ = TypeInfo(TTimeSpan) then


(*) Nachtrag: Ich würde sicherheitshalber noch ein Assert(SizeOf(TTimeSpan) = SizeOf(Int64)) reinschreiben, dass es nicht irgendwann bei einer Änderung ein böses Erwachen gibt (das wird sogar zur Compilezeit ausgewertet, so dass das Assert gar nicht in der Binary landet, wenn die Bedingung wahr ist)

Es ist sogar möglich, den Fehler zur Compilezeit zu bekommen, seh ich gerade:
Delphi-Quellcode:
{$IF SizeOf(TTimeSpan) <> SizeOf(Int64)}{$MESSAGE ERROR 'TTimeSpan does not have the same size as Int64'}{$IFEND}


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