Jump to content
3ddark

Rtti Is it possible One Property Attribute

Recommended Posts

Hello,Can I access the attribute value of only one property?
For example :

var
  LDay: TSysDay;
  LFieldName: string;

LFieldName := GetAttribute(LDay.Day);

Sending a property of the class, such as getting the attribute information of it.

type
  TFieldNameAttribute = class(TCustomAttribute)
  strict private
    FName: string;
  public
    property Name: string read FName;
    constructor Create(AName: string);
  end;

//----------------------------------------------------
type
  [TSchemaNameAttribute('public')]
  [TTableNameAttribute('sys_days')]
  TSysDay = class(TTableBase)
  private
    FId: Int64;
    FDay: WideString;
    procedure SetId(const Value: Int64);
    procedure SetDay(const Value: WideString);
   public
    [TFieldNameAttribute('id')]
    property Id: Int64 read FId write SetId;

    [TFieldNameAttribute('day')]
    property Day: WideString read FDay write SetDay;
  end;
//---------------------------------------
function TTable.GetTableName: string;
var
  LC: TRttiContext;
  LT: TRttiType;
  LA: TCustomAttribute;
begin
  Result := '';
  LC := TRttiContext.Create;
  try
    LT := LC.GetType(Self.ClassType);
    for LA in LT.GetAttributes() do
      if LA is TTableNameAttribute then
      begin
        Result := TTableNameAttribute(LA).Name;
        Exit;
      end;
//Result is "sys_day"
  finally
    LC.Free
  end;
end;
//---------------------------------------
function TTable.GetFieldNames: string;
var
  LC: TRttiContext;
  LT: TRttiType;
  LP: TRttiProperty;
  LA: TCustomAttribute;
begin
  Result := '';
  LC := TRttiContext.Create;
  try
    LT := LC.GetType(Self.ClassType);
    for LP in LT.GetProperties() do
      for LA in LP.GetAttributes() do
        if LA is TFieldNameAttribute then
          Result := Result + TFieldNameAttribute(LA).Name + ', ';
    if Trim(Result) <> '' then
    begin
      Result := Trim(Result);
      Result := LeftStr(Result, Length(Result)-1);
    end;
//Result is "id, day"
  finally
    LC.Free
  end;
end;

 

Share this post


Link to post

You sort of posted the answer with your question.

Not sure what you are trying to improve?

Share this post


Link to post
5 hours ago, Lars Fosdal said:

You sort of posted the answer with your question.

Not sure what you are trying to improve?

I know it's a stupid question.

Can I get the attribute value for only one property?

Without sending any information as a string.
As an example I get the TableName via ClassType

Table is an object. But properties not and object

Share this post


Link to post
type
  [TTableNameAttribute('sys_days')]
  TSysDay = class(TTableBase)
  private
    FId: Int64;
    FDay: WideString;
...
...
...
   public
    [TFieldNameAttribute('id')]
    property Id: Int64 read FId write SetId;

    [TFieldNameAttribute('day')]
    property Day: WideString read FDay write SetDay;

    [TFieldNameAttribute('a')] property A: WideString
    [TFieldNameAttribute('b')] property B: Int64
    [TFieldNameAttribute('c')] property C: Double
  end;

Can I just get the value of an attribute

GetFieldAttribe('a');	//wrong example. Here I can check and find in the loop with the incoming parameter

GetFieldAttribe(Self.A);	//correct example. Here A is WideString Member. Not a class, not a object

 

Share this post


Link to post

In this code:

var
  LDay: TSysDay;
  LFieldName: string;

LFieldName := GetAttribute(LDay.Day);

You are passing in the value that is returned by reading the Day property. You are not passing in the property itself.  You can't pass around properties, that is simply not allowed.  You will have to pass in the property's name as a string and use RTTI to access it, eg:

function GetFieldAttribute(Obj: TObject; const PropName: string): string;
var
  LC: TRttiContext;
  LT: TRttiType;
  LP: TRttiProperty;
  LA: TCustomAttribute;
begin
  Result := '';
  LC := TRttiContext.Create;
  try
    LT := LC.GetType(Obj.ClassType);
    LP := LT.GetProperty(PropName);
    if LP <> nil then begin
      for LA in LP.GetAttributes() do begin
        if LA is TFieldNameAttribute then
          Exit(TFieldNameAttribute(LA).Name);
        end;
      end;
    end;
  finally
    LC.Free
  end;
end;
var
  LDay: TSysDay;
  LFieldName: string;

LFieldName := GetFieldAttribute(LDay, 'Day');
LFieldName := GetFieldAttribute(LDay, 'A');
LFieldName := GetFieldAttribute(LDay, 'B');
LFieldName := GetFieldAttribute(LDay, 'C');

 

Edited by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×