I have a class with published props which I serialize into XML.
MyAttr = class(TCustomAttribute)
private
FName: string;
public
constructor Create(const Name: string);
property Name: string read FName write FName;
end;
MyClass = class(TPersistent)
private
FClassCaption: string;
published
[MyAttr('Class')]
property ClassCaption: string read FClassCaption write FClassCaption;
end;
Since XML size is crucial, I use attributes to give shorter name for property (i.e I can't define a property named 'Class'). Serialization implemented the following way:
lPropCount := GetPropList(PTypeInfo(Obj.ClassInfo), lPropList);
for i := 0 to lPropCount - 1 do begin
lPropInfo := lPropList^[i];
lPropName := string(lPropInfo^.Name);
if IsPublishedProp(Obj, lPropName) then begin
ItemNode := RootNode.AddChild(lPropName);
ItemNode.NodeValue := VarToStr(GetPropValue(Obj, lPropName, False));
end;
end;
I need condition like: if property marked with MyAttr, get "MyAttr.Name" instead of "lPropInfo^.Name".
You can use this function to get your attribute name from the given property (wrote it in a minute, probably needs some optimization):
uses
SysUtils,
Rtti,
TypInfo;
function GetPropAttribValue(ATypeInfo: Pointer; const PropName: string): string;
var
ctx: TRttiContext;
typ: TRttiType;
Aprop: TRttiProperty;
attr: TCustomAttribute;
begin
Result := '';
ctx := TRttiContext.Create;
typ := ctx.GetType(ATypeInfo);
for Aprop in typ.GetProperties do
begin
if (Aprop.Visibility = mvPublished) and (SameText(PropName, Aprop.Name)) then
begin
for attr in AProp.GetAttributes do
begin
if attr is MyAttr then
begin
Result := MyAttr(attr).Name;
Exit;
end;
end;
Break;
end;
end;
end;
Call it like this:
sAttrName:= GetPropAttribValue(obj.ClassInfo, lPropName);
So if this function returns empty string it means that property is not marked with MyAttr and then you need to use "lPropInfo^.Name".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With