@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
Mein aktuelles Test-Projekt:
Delphi-Quellcode:
// 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;
Ich denke, darauf kann man ganz gut aufbauen
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
Video zu RTTI und Attributen in D2010.