Jump to content
aehimself

How to get PTypeInfo of TRttiProperty / TRttiField

Recommended Posts

For a long time I am using a custom settings class in most of my applications to store it's data. They all have a .AsJSON property to export / import everything, which is automatically called by .Load and .Save. It's working perfectly. The only drawback is that I had to write the getter and setter methods for each instance, even if it's only a sub-class of the main settings. And it was getting tiring.

I started to experiment with RTTI to make the class detect it's own properties in the getter and setter so I finally can forget about these in general situations. Exporting works like a charm; I only could not properly handle TLists but I wrote a custom list wrapper for the rescue.

 

The importing (loading from JSON) part caused some headache, which I can't seem to solve. One part is left, if the property / field is an array type. The inner helper method looks like this:

Function TApplicationSettings.JSONToValue(inJSON: TJSONValue; inTypeInfo: PTypeInfo): TValue;
Var
 enum: TJSONArray.TEnumerator;
 valarray: TArray<TValue>;
 a: Integer;
Begin
 Result := TValue.Empty;
 Case inTypeInfo.Kind Of
  [...]
  tkArray, tkDynArray:
  Begin
   enum := TJSONArray(inJSON).GetEnumerator;
   SetLength(valarray, TJSONArray(inJSON).Count);
   If Assigned(enum) Then Try
    a := 0;
    While enum.MoveNext Do
    Begin
     valarray[a] := JSONToValue(enum.Current, inTypeInfo);
     Inc(a);
    End;
   Finally
    enum.Free;
   End;
   Result := TValue.FromArray(inTypeInfo, valarray);
  End;
 End;
End;

..and the outer helper:

Procedure TApplicationSettings.JSONToRttiMember(inJSON: TJSONValue; inRttiMember: TRttiMember);
Var
 val: TValue;
 pi: PTypeInfo;
 ppi: PPropInfo;
Begin
 If Not Assigned(inJSON) Then Exit;
 ppi := GetPropInfo(Self, inRttiMember.Name);
 If Not Assigned(ppi) Then Exit;
 pi := ppi^.PropType^;
 val := JSONToValue(inJSON, pi);
 If val.IsEmpty Then Exit;
 If inRttiMember Is TRttiProperty Then (inRttiMember As TRttiProperty).SetValue(Self, val)
   Else
 If inRttiMember Is TRttiField Then (inRttiMember As TRttiField).SetValue(Self, val);
End;

This most possibly where my mistake is, as GetPropInfo always returns nil. Before this solution I passed the (PropertyType / FieldType).TypeKind as a parameter to the inner helper, but in that case I won't have access to PTypeInfo, which is needed for the TValue.FromArray.

So the question is; how can I extract the PTypeInfo of an RTTI field / property? Because the code above doesn't, that's for sure 🙂

Share this post


Link to post

I saw handle in the list; I just quickly passed by it as it usually means something different... Thank you!

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

×