mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-01 21:02:36 +02:00
160 lines
3.4 KiB
ObjectPascal
160 lines
3.4 KiB
ObjectPascal
{ %OPT=-gh }
|
|
|
|
program tw36196;
|
|
|
|
{$mode objfpc}{$H+}
|
|
{$modeswitch prefixedattributes}
|
|
|
|
uses
|
|
{heaptrc, }SysUtils, typinfo, {%H-}rtti;
|
|
|
|
type
|
|
|
|
IntRangeAttribute = class(TCustomAttribute)
|
|
private
|
|
FMinValue,
|
|
FMaxValue: Integer;
|
|
public
|
|
constructor Create(aMin, aMax: Integer);
|
|
property MinValue: Integer read FMinValue;
|
|
property MaxValue: Integer read FMaxValue;
|
|
end;
|
|
|
|
DefaultStrAttribute = class(TCustomAttribute)
|
|
private
|
|
FValue: string;
|
|
public
|
|
constructor Create;
|
|
constructor Create(const aValue: string);
|
|
property Value: string read FValue;
|
|
end;
|
|
|
|
CheckAttribute = class(TCustomAttribute)
|
|
private
|
|
FChecked: Boolean;
|
|
public
|
|
constructor Create;
|
|
constructor Create(aValue: Boolean);
|
|
property Checked: Boolean read FChecked;
|
|
end;
|
|
|
|
[Check(True)]
|
|
TMyClass = class
|
|
private
|
|
FName,
|
|
FDescr: string;
|
|
FId: Integer;
|
|
published
|
|
[DefaultStr]
|
|
property Name: string read FName write FName;
|
|
[DefaultStr('nice description')]
|
|
property Description: string read FDescr write FDescr;
|
|
[IntRange(100, 10000)]
|
|
property Id: Integer read FId write FId;
|
|
end;
|
|
|
|
[DefaultStr('this is TMyRec')][IntRange(0, 100)]
|
|
TMyRec = record
|
|
Name: string;
|
|
Value: Integer;
|
|
end;
|
|
|
|
[Check][IntRange(-10000, 10000)]
|
|
TMyInt = type Integer;
|
|
|
|
{ CheckAttribute }
|
|
|
|
constructor CheckAttribute.Create;
|
|
begin
|
|
FChecked := False;
|
|
end;
|
|
|
|
constructor CheckAttribute.Create(aValue: Boolean);
|
|
begin
|
|
FChecked := aValue;
|
|
end;
|
|
|
|
{ DefaultStrAttribute }
|
|
|
|
constructor DefaultStrAttribute.Create;
|
|
begin
|
|
FValue := 'Unassigned';
|
|
end;
|
|
|
|
constructor DefaultStrAttribute.Create(const aValue: string);
|
|
begin
|
|
FValue := aValue;
|
|
end;
|
|
|
|
{ TIntRangeAttribute }
|
|
|
|
constructor IntRangeAttribute.Create(aMin, aMax: Integer);
|
|
begin
|
|
FMinValue := aMin;
|
|
FMaxValue := aMax;
|
|
end;
|
|
|
|
procedure PrintAttribute(Attr: TCustomAttribute);
|
|
begin
|
|
if not Assigned(Attr) then
|
|
exit;
|
|
WriteLn(' Found attribute ', Attr.ClassName, ':');
|
|
if Attr is DefaultStrAttribute then
|
|
WriteLn(' property Value has value "', DefaultStrAttribute(Attr).Value, '"')
|
|
else
|
|
if Attr is IntRangeAttribute then
|
|
begin
|
|
WriteLn(' property MinValue has value ', IntRangeAttribute(Attr).MinValue);
|
|
WriteLn(' property MaxValue has value ', IntRangeAttribute(Attr).MaxValue);
|
|
end
|
|
else
|
|
if Attr is CheckAttribute then
|
|
WriteLn(' property Checked has value ', CheckAttribute(Attr).Checked);
|
|
end;
|
|
|
|
procedure PrintClassAttributes(aClass: TClass);
|
|
var
|
|
RCtx: TRttiContext;
|
|
RType: TRttiType;
|
|
Prop: TRttiProperty;
|
|
Attr: TCustomAttribute;
|
|
begin
|
|
RCtx := TRttiContext.Create;
|
|
try
|
|
RType := RCtx.GetType(aClass);
|
|
WriteLn(RType.Name, ' attributes:');
|
|
for Attr in RType.GetAttributes do
|
|
PrintAttribute(Attr);
|
|
for Prop in RType.GetProperties do
|
|
for Attr in Prop.GetAttributes do
|
|
PrintAttribute(Attr);
|
|
finally
|
|
RCtx.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure PrintTypeAttributes(aInfo: PTypeInfo);
|
|
var
|
|
RCtx: TRttiContext;
|
|
RType: TRttiType;
|
|
Attr: TCustomAttribute;
|
|
begin
|
|
RCtx := TRttiContext.Create;
|
|
try
|
|
RType := RCtx.GetType(aInfo);
|
|
WriteLn(RType.Name, ' attributes:');
|
|
for Attr in RType.GetAttributes do
|
|
PrintAttribute(Attr);
|
|
finally
|
|
RCtx.Free;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
HaltOnNotReleased:=True;
|
|
//SetHeapTraceOutput('heap.log');
|
|
PrintClassAttributes(TMyClass);
|
|
PrintTypeAttributes(TypeInfo(TMyRec));
|
|
PrintTypeAttributes(TypeInfo(TMyInt));
|
|
end.
|