How to get the value of a property and how to get the property where the attribute is declared?

1

Let's say I'm creating an Attribute like this:

TCompareAttribute = class(TCustomAttribute)
private
  FPropertyToCompare: string;
public
  constructor Create(APropertyToCompare: string);
  function IsValid: boolean;
end;

implementation

...
function TCompareAttribute.IsValid: boolean;
var
  ctx: TRttiContext;
begin
  ctx := TRttiContext.Create;
  try
    prop := ctx.GetType(self.ClassParent).GetProperty(FPropertyToComparer);
    if prop = nil then
      raise Exception.Create('A propriedade não existe!');

    result := prop.GetValue() = ??

  finally
    ctx.Free;
  end;
end;

The purpose of this attribute is to compare two properties and check if they have the same value, if they are the same.

I have two questions:

  

How to get property value in variable "prop" without instance of object   e;

     

2nd. How do I get the property where the attribute is declared and then compare the values?

    
asked by anonymous 25.02.2015 / 15:18

1 answer

1

If I understand your question, this will depend somewhat on the way your project was modeled, because there are N ways to dynamically get information about an object's properties.

Answering your questions:

  

How to get the property value in the variable "prop" without the   object instance e;

A possible form would be by class name and property via string, eg:

var
  ctx: TRttiContext;
  prop: TRttiProperty;
begin
  ctx := TRttiContext.Create;
  try
    prop := ctx.FindType('Unit1.TForm1').GetProperty('Test1');
    ShowMessage(prop.Name);
  finally
    ctx.Free;
  end;
end;

Note that I only gave the form and property name, that is, I did not pass any instances.

  

2nd. How to get the property where the attribute is declared by then   compare the values?

In fact it would be "How do I check if an attribute is declared in a property?", ie:

var
  ctx: TRttiContext;
  prop: TRttiProperty;
  attr: TCustomAttribute;
begin
  ctx := TRttiContext.Create;
  try
    for prop in ctx.FindType('Unit1.TForm1').GetProperties do
      for attr in prop.GetAttributes do
        if attr is TMyAttribute then
          ShowMessage(prop.Name);
  finally
    ctx.Free;
  end;
end;

With this, you can exit the loop if the given property declares the attribute you are looking for.

Here's an example of how to scan the properties of a form, showing its name, declared attribute, and assigned value:

type
  TMyAttribute = class(TCustomAttribute)
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    FTest1: string;
    FTest2: string;
  published
    [TMyAttribute]
    property Test1: string read FTest1;
    [TMyAttribute]
    property Test2: string read FTest2;
  end;

implementation

procedure TForm1.FormCreate(Sender: TObject);
begin
  FTest1 := 'A';
  FTest2 := 'B';
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ctx: TRttiContext;
  prop: TRttiProperty;
  attr: TCustomAttribute;
begin
  ctx := TRttiContext.Create;
  try
    for prop in ctx.FindType('Unit1.TForm1').GetProperties do
      for attr in prop.GetAttributes do
        if attr is TMyAttribute then
          ShowMessageFmt(
            'Propriedade "%s" que declara o atributo "%s" tem o valor "%s"',
            [prop.Name, attr.ClassName, prop.GetValue(Self).AsString]);
  finally
    ctx.Free;
  end;
end;

Hope this helps! =)

    
03.04.2015 / 04:02