aehimself 396 Posted April 24, 2020 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
pyscripter 689 Posted April 24, 2020 GetProperty(Name).PropertyType.Handle 1 Share this post Link to post
aehimself 396 Posted April 25, 2020 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