![]() |
Delphi-Version: 5
Feldwerte eines Records über den Feldindex abrufen
Hallo Zusammen,
ich habe ein Record aus mehreren String-Feldern. Diese möchte ich gerne über eine Schleife durchgehen. Gibt es eine RTTI Methode um dessen Wert über seinen Feldindex abzurufen?
Delphi-Quellcode:
type
TMyRecord = Record FeldA, FeldB, FeldC: String; var MyRecord: TMyRecord; begin //wie kann ich bitte auf das FeldC über seinen Index=2 zugreifen? //in etwa so: MyRecord[2] end; |
AW: Feldwerte eines Records über den Feldindex abrufen
|
AW: Feldwerte eines Records über den Feldindex abrufen
Hallo,
das funktioniert auch ohne RTTI:
Delphi-Quellcode:
type
TMyRecord = packed Record FeldA, FeldB, FeldC: String; End; var MyRecord: TMyRecord; VAR // MyArray: Array[1..3] of String ABSOLUTE MyRecord; // oder so: MyArray: Array[1..3] of String ABSOLUTE MyRecord.FeldA; Begin MyRecord.FeldA:= 'AAAAAAAAAAAA'; MyRecord.FeldB:= 'BBBBBBBBBBBB'; MyRecord.FeldC:= 'CCCCCCCCCCCC'; WriteLn('MyArray[1] = ', MyArray[1]); WriteLn('MyArray[2] = ', MyArray[2]); WriteLn('MyArray[3] = ', MyArray[3]); ReadLn; End. |
AW: Feldwerte eines Records über den Feldindex abrufen
Zitat:
Delphi-Quellcode:
Bis bald...
function GetFieldValue(pmTypeInfo: Pointer; pmInstance: Pointer; pmFieldIdx: Integer): TValue;
begin if (pmTypeInfo <> Nil) and (pmInstance <> Nil) and (pmFieldIdx >= 0) then begin var rttiType: TRttiType := TRttiContext.Create.GetType(pmTypeInfo); if rttiType <> Nil then begin var rttiFields: TArray<TRttiField> := rttiType.GetFields; if Length(rttiFields) > pmFieldIdx then Exit(rttiFields[pmFieldIdx].GetValue(pmInstance)); end; end; Result := TValue.Empty; end; var rec: TMyRecord; begin rec.FeldC := 'Test'; ShowMessage(GetFieldValue(TypeInfo(TMyRecord), @rec, 2).ToString); Thomas |
AW: Feldwerte eines Records über den Feldindex abrufen
Das kann man auch mit einem Record-Helper realisieren:
Delphi-Quellcode:
Der Aufruf gestaltet sich dann in etwa so:
type
TMyRecord = record FeldA, FeldB, FeldC: String; end; type TMyRecordHelper = record helper for TMyRecord private type TMockArray = array[0..0] of string; private function GetItems(Index: Integer): string; procedure SetItems(Index: Integer; const Value: string); public property Items[Index: Integer]: string read GetItems write SetItems; default; end; function TMyRecordHelper.GetItems(Index: Integer): string; begin {$R-} Result := TMockArray(FeldA)[Index - 1]; {$R+} end; procedure TMyRecordHelper.SetItems(Index: Integer; const Value: string); begin {$R-} TMockArray(FeldA)[Index - 1] := Value; {$R+} end;
Delphi-Quellcode:
var Tmp: TMyRecord;
Tmp.FeldA := 'Hallo'; Tmp.FeldB := 'Delphi'; Tmp.FeldC := 'Welt'; var Satz: string; for var I := 1 to 3 do Satz := Satz + ' ' + Tmp[I]; Writeln(Satz.TrimLeft); Readln; |
AW: Feldwerte eines Records über den Feldindex abrufen
oder manuell
Delphi-Quellcode:
type
TMyRecord = packed record private function GetFeld(idx: Integer): string; procedure SetFeld(idx: Integer; const Value: string); public FeldA, FeldB, FeldC: string; property Feld[idx: Integer]: string read GetFeld write SetFeld; end; // oder TMyRecord = packed record private FFeld: array[0..2] of string; function GetFeld(idx: Integer): string; procedure SetFeld(idx: Integer; const Value: string); public property FeldA: string index 0 read GetFeld write SetFeld; property FeldB: string index 1 read GetFeld write SetFeld; property FeldC: string index 2 read GetFeld write SetFeld; property Feld[idx: Integer]: string read GetFeld write SetFeld; end; // oder (wobei, neeeeeee) TMyRecord = packed record private function GetFeld(idx: Integer): string; procedure SetFeld(idx: Integer; const Value: string); public Feld: array[0..2] of string; property FeldA: string index 0 read GetFeld write SetFeld; property FeldB: string index 1 read GetFeld write SetFeld; property FeldC: string index 2 read GetFeld write SetFeld; end; // oder .... |
AW: Feldwerte eines Records über den Feldindex abrufen
Hallo Zusammen,
oh, so viele Variante, vielen lieben Dank. Ich benötige über den Index den Namen und Feldwert. Deshalb versucht ich die Varianten von @mytbo
Delphi-Quellcode:
function GetFieldValue(pmTypeInfo: Pointer; pmInstance: Pointer; pmFieldIdx: Integer): TValue;
begin if (pmTypeInfo <> Nil) and (pmInstance <> Nil) and (pmFieldIdx >= 0) then begin var rttiType: TRttiType := TRttiContext.Create.GetType(pmTypeInfo); if rttiType <> Nil then begin var rttiFields: TArray<TRttiField> := rttiType.GetFields; if Length(rttiFields) > pmFieldIdx then Exit(rttiFields[pmFieldIdx].GetValue(pmInstance)); end; end; Result := TValue.Empty; end; var rec: TMyRecord; begin rec.FeldC := 'Test'; ShowMessage(GetFieldValue(TypeInfo(TMyRecord), @rec, 2).ToString);
Delphi-Quellcode:
Hat jemand eine Idee?
var rttiFields: TArray<TRttiField> := rttiType.GetFields;
//das TArray<TRttiField> hier bekomme ich einen Fehler angezeigt E2010 Inkompatible Typen 'String' und 'TValue' |
AW: Feldwerte eines Records über den Feldindex abrufen
Zitat:
|
AW: Feldwerte eines Records über den Feldindex abrufen
Sorry Uwe,
das war mir nicht klar. |
AW: Feldwerte eines Records über den Feldindex abrufen
Zitat:
Delphi-Quellcode:
Bis bald...
function GetFieldNameAndValue(pmTypeInfo: Pointer; pmInstance: Pointer; pmFieldIdx: Integer; out pmoFieldName: String; out pmoFieldValue: TValue): Boolean;
var rttiType: TRttiType; rttiFields: TArray<TRttiField>; begin if (pmTypeInfo <> Nil) and (pmInstance <> Nil) and (pmFieldIdx >= 0) then begin rttiType := TRttiContext.Create.GetType(pmTypeInfo); if rttiType <> Nil then begin rttiFields := rttiType.GetFields; if Length(rttiFields) > pmFieldIdx then begin pmoFieldName := rttiFields[pmFieldIdx].Name; pmoFieldValue := rttiFields[pmFieldIdx].GetValue(pmInstance); Exit(True); end; end; end; Result := False; end; var rec: TMyRecord; fieldName: String; fieldValue: TValue; begin rec.FeldC := 'Test'; if GetFieldNameAndValue(TypeInfo(TMyRecord), @rec, 2, fieldName, fieldValue) then ShowMessage(Format('Name: %s, Value: %s', [fieldName, fieldValue.ToString])); end; Thomas |
AW: Feldwerte eines Records über den Feldindex abrufen
Hallo Thomas,
Ich habe deine Version anwenden können, es funktioniert perfekt. Das mit der Fehlermeldung lag daran dass bei Value das Result ein TValue ist und ich String benötigte. Das habe ich nicht gleich gesehen. Jetzt funktioniert alles perfekt.
Delphi-Quellcode:
Vielen Dank an alle und Euch noch eine schöne Zeit.
var rttiFields: TArray<TRttiField> := rttiType.GetFields;
//das TArray<TRttiField> hier bekomme ich einen Fehler angezeigt E2010 Inkompatible Typen 'String' und 'TValue' |
AW: Feldwerte eines Records über den Feldindex abrufen
Ich glaube zwar, dass Delphi beim String, Interface oder Variant aus dem OUT ein VAR macht, oder vielleicht vor Übergabe den Wert auf NIL setzt,
aber am Besten niemals für Managed-Types ein OUT benutzen. Wenn OUT wirklich das macht, was es eigentlich soll, dann wäre das eine super Stelle für Speicherleck. :stupid: |
AW: Feldwerte eines Records über den Feldindex abrufen
Zitat:
Delphi-Quellcode:
Bis bald...
uses
mormot.core.base, mormot.core.json, mormot.core.rtti; function GetFieldNameAndValue(pmTypeInfo: PRttiInfo; pmInstance: Pointer; pmFieldIdx: Integer; out pmoFieldValue: Variant): String; var rttiType: TRttiType; rttiFields: TRttiCustomPropDynArray; begin if (pmTypeInfo <> Nil) and (pmInstance <> Nil) and (pmFieldIdx >= 0) then begin rttiFields := Rtti[pmTypeInfo].Props.List; if Length(rttiFields) > pmFieldIdx then begin rttiFields[pmFieldIdx].GetValueVariant(pmInstance, TVarData(pmoFieldValue)); Exit(Utf8ToString(rttiFields[pmFieldIdx].Name)); end; end; Result := ''; end; var rec: TMyRecord; fieldName: String; fieldValue: Variant; begin rec.FeldC := 'Test'; fieldName := GetFieldNameAndValue(TypeInfo(TMyRecord), @rec, 2, fieldValue); if fieldName <> '' then ShowMessage(Format('Name: %s, Value: %s', [fieldName, VarToStr(fieldValue)])); Thomas |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:40 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz