我有一个发布道具的类,我将其序列化为
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;
由于XML大小至关重要,我使用属性为属性提供更短的名称(即我无法定义名为’Class’的属性).
序列化通过以下方式实现:
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;
解决方法
您可以使用此函数从给定属性中获取属性名称(在一分钟内写入,可能需要一些优化):
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;
这样叫:
sAttrName:= GetPropAttribValue(obj.ClassInfo,lPropName);
因此,如果此函数返回空字符串,则表示该属性未使用MyAttr标记,然后您需要使用“lPropInfo ^ .Name”.