3ddark 3 Posted October 12, 2022 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
Lars Fosdal 1792 Posted October 13, 2022 You sort of posted the answer with your question. Not sure what you are trying to improve? Share this post Link to post
3ddark 3 Posted October 13, 2022 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
3ddark 3 Posted October 13, 2022 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
Remy Lebeau 1398 Posted October 13, 2022 (edited) 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 October 13, 2022 by Remy Lebeau Share this post Link to post