![]() |
RTTI - Property - SetValue
Ich versuche, RTTI unter XE zu verstehen und zu nutzen.
Ich habe eine
Delphi-Quellcode:
mit den Propertys
Klasse TTest
Delphi-Quellcode:
und
S: String
Delphi-Quellcode:
;
I: Integer
Nun möchte ich mit
Delphi-Quellcode:
und analog
SetString(T, 'S', 'Text')
Delphi-Quellcode:
Werte zuweisen:
SetInteger(T, 'I', 100)
Delphi-Quellcode:
Die
procedure SetString(T: TTest; PropName: String; Value: String);
var Context: TRttiContext; ClassInfo: TRttiType; PropInfo: TRttiProperty; PropValue: TValue; begin if not Assigned(T) then Exit; Context := TRttiContext.Create; ClassInfo := Context.GetType(T.ClassType); PropInfo := ClassInfo.GetProperty(PropName); if Assigned(PropInfo) then begin { so könnte man den Wert auslesen: PropValue := PropInfo.GetValue(T); if PropValue.Kind = tkString then Result := PropValue.AsString wie kann ich einen Wert schreiben??? im Grunde brauche ich so etwas wie T.PropertyByName('PropName').AsString := Value } end; context.Free; end; procedure SetInteger(T: TTest; PropName: String; Value: Integer); ...Variante mit Integer ![]() Weiß jemand Rat? |
AW: RTTI - Property - SetValue
Ich kann mich täuschen, aber LVar siht mir in diesem Beispiel wie die gewünschte Instanz aus und nicht wie eine Klasse.
|
AW: RTTI - Property - SetValue
So gehts:
Delphi-Quellcode:
// Testklasse
TTest = class private FStr: string; public/published property Str: string read FStr write FStr; end; // Wert schreiben if Assigned(PropInfo) then begin PropValue := TValue.From(Value); PropInfo.SetValue(T, PropValue); end; |
AW: RTTI - Property - SetValue
@himitsu
Na ja, im SetProperty-Beispiel wird LVar eben nicht verwendet. Das kann ich daher nicht einordnen und nachvollziehen. @Björn Danke, das hat geholfen :thumb: Mein aktuelles Test-Projekt:
Delphi-Quellcode:
Ich denke, darauf kann man ganz gut aufbauen :)
// mein Attribut...
type AttrOd = class(TCustomAttribute); // meine Klasse... public constructor Create(AOwner: TComponent); override; destructor Destroy; override; [AttrOd] property Name: String read get_Name write set_Name; [AttrOd] property Number: Integer read get_Number write set_Number; // Read/Write propertys // // Testweise werden die propertys einfach in eine Stringlist geschrieben und wieder geladen. Diese sieht so aus: // Name=xxx // Number=111 procedure TodData.ReadPropValues(const od: Tod); var Context: TRttiContext; RttiType: TRttiType; PropInfo: TRttiProperty; F: Boolean; Attr: TCustomAttribute; Value: TValue; sl: tstringlist; begin if not Assigned(od) then Exit; sl := tstringlist.Create; sl.LoadFromFile('sl.txt'); Context := TRttiContext.Create; RttiType := Context.GetType(od.ClassType); if Assigned(RttiType) then begin for PropInfo in RttiType.GetProperties do begin F := False; for Attr in PropInfo.GetAttributes do begin if Attr is AttrOd then F := True; end; if F then begin Value := TValue.Empty; case PropInfo.PropertyType.TypeKind of tkUnknown: ; tkInteger: Value := TValue.From(StrToInt(sl.Values[PropInfo.Name])); tkChar: ; tkEnumeration: ; tkFloat: ; tkString: Value := TValue.From(sl.Values[PropInfo.Name]); tkSet: ; tkClass: ; tkMethod: ; tkWChar: ; tkLString: ; tkWString: ; tkVariant: ; tkArray: ; tkRecord: ; tkInterface: ; tkInt64: ; tkDynArray: ; tkUString: Value := TValue.From(sl.Values[PropInfo.Name]); tkClassRef: ; tkPointer: ; tkProcedure: ; end; if not Value.IsEmpty then PropInfo.SetValue(od, Value); end; end; end; sl.Free; Context.Free; end; procedure TodData.WritePropValues(const od: Tod); var Context: TRttiContext; RttiType: TRttiType; PropInfo: TRttiProperty; F: Boolean; Attr: TCustomAttribute; Value: TValue; sl: tstringlist; begin if not Assigned(od) then Exit; sl := tstringlist.Create; Context := TRttiContext.Create; RttiType := Context.GetType(od.ClassType); if Assigned(RttiType) then begin for PropInfo in RttiType.GetProperties do begin F := False; for Attr in PropInfo.GetAttributes do begin if Attr is AttrOd then F := True; end; if F then begin Value := PropInfo.GetValue(od); case Value.Kind of tkUnknown: ; tkInteger: sl.Values[PropInfo.Name] := IntToStr(Value.AsInteger); tkChar: ; tkEnumeration: ; tkFloat: ; tkString: sl.Values[PropInfo.Name] := Value.AsString; tkSet: ; tkClass: ; tkMethod: ; tkWChar: ; tkLString: ; tkWString: ; tkVariant: ; tkArray: ; tkRecord: ; tkInterface: ; tkInt64: ; tkDynArray: ; tkUString: sl.Values[PropInfo.Name] := Value.AsString; tkClassRef: ; tkPointer: ; tkProcedure: ; end; end; end; end; sl.SaveToFile('sl.txt'); sl.Free; Context.Free; end; Das Schöne dabei ist, mit dem Attribut "AttrOd" kann ich alle Propertys "markieren", die gespeichert und geladen werden sollen. Außerdem können diese public und müssen nicht published sein. (Felder (Variablen) können sogar privat sein.) Genaueres zeigt Daniel in seinem ![]() |
AW: RTTI - Property - SetValue
Das ist wahrlich ein Fehler. Schaut man aber direkt auf der
![]() |
AW: RTTI - Property - SetValue
Hallo Armin,
danke, das stimmt. Deinen ![]() In Verbindung mit Attributen ist RTTI schon sehr interessant. Wenn man Objekte speichern möchte, ist das ein guter Grund, ggf. auf D2010 bzw. XE upzugraden. |
AW: RTTI - Property - SetValue
Oh ja, das stimmt auf jedenfall. Ebenso, wenn man sich einen eigenes ORM-Framework schreiben will, kann das echt sehr praktisch sein.
|
AW: RTTI - Property - SetValue
Ich habe noch ein Problem mit den Aufzählungstypen:
Delphi-Quellcode:
Ich möchte hier natürlich universelle Aufzählungstypen zuweisen. Mit GetEnumValue erhalte ich den korrekten Ordinalwert.
Value := TValue.Empty;
case PropInfo.PropertyType.TypeKind of tkUnknown: ; tkInteger: Value := TValue.From(StrToIntDef(PropValue, 0)); tkChar: ; tkEnumeration: Value := TValue.From(TXyz(GetEnumValue(PropInfo.PropertyType.Handle, PropValue))); // <-- HIER tkFloat: ; ... end; if not Value.IsEmpty then PropInfo.SetValue(od, Value); Wenn hart in Txyz caste, funktioniert auch die Varianten-Zuweisung korrekt. Wenn aber TAbc eingelesen werden soll, funktioniert das natürlich nicht. Kann ich irgendwie
Delphi-Quellcode:
oder ähnliches verwenden?
PropInfo.MYTYPE(GetEnumValue(PropInfo.PropertyType.Handle, PropValue))
Irgendwo liegt hoffentlich ein Handle auf den Typ TXyz bzw. TAbc ... bitte, bitte, bitte :!: Oder kann ich SetValue irgendwie zwingen, einen Ordinalwert für Aufzählungstypen anzunehmen? |
AW: RTTI - Property - SetValue
Liste der Anhänge anzeigen (Anzahl: 1)
Sorry, für den Push.
Das Handle ist offenbar schon das richtige (Name=TStateType). An der Position des Pfeils will ich nun in diesen "Typ" casten. |
AW: RTTI - Property - SetValue
Ich habe
![]()
Delphi-Quellcode:
So funktioniert es. Der Rest sollte dann zu schaffen sein. :)
tkEnumeration:
Value := TValue.FromOrdinal(PropInfo.PropertyType.Handle, GetEnumValue(PropInfo.PropertyType.Handle, PropValue)); |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:35 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 by Thomas Breitkreuz