Quick.Config.pas 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. { ***************************************************************************
  2. Copyright (c) 2015-2018 Kike Pérez
  3. Unit : Quick.Config
  4. Description : Load/Save config from/to JSON file
  5. Author : Kike Pérez
  6. Version : 1.2
  7. Created : 26/01/2017
  8. Modified : 12/02/2018
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Config;
  22. interface
  23. uses
  24. System.Classes,
  25. System.SysUtils,
  26. System.Rtti,
  27. {$IF CompilerVersion >= 32.0}
  28. JSON.Types,
  29. JSON.Serializers;
  30. {$ELSE}
  31. Rest.Json.Types,
  32. Rest.Json;
  33. {$ENDIF}
  34. type
  35. TDateTimeZone = (tzLocal, tzUTC);
  36. IAppConfigProvider<T> = interface
  37. ['{D55B1EBF-47F6-478B-8F70-9444575CB825}']
  38. procedure Load(var cConfig : T);
  39. procedure Save(var cConfig : T);
  40. end;
  41. TAppConfigProviderBase<T : class> = class(TInterfacedObject,IAppConfigProvider<T>)
  42. private
  43. fCreateIfNotExists : Boolean;
  44. public
  45. constructor Create(var cConfig : T); virtual;
  46. property CreateIfNotExists : Boolean read fCreateIfNotExists write fCreateIfNotExists;
  47. function InitObject : T;
  48. procedure Load(var cConfig : T); virtual; abstract;
  49. procedure Save(var cConfig : T); virtual; abstract;
  50. end;
  51. TApplyConfigEvent = procedure of object;
  52. [JsonSerialize(TJsonMemberSerialization.&Public)]
  53. TAppConfig = class
  54. private
  55. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  56. fOnApplyConfig : TApplyConfigEvent;
  57. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  58. fDateTimeZone: TDateTimeZone;
  59. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  60. fJsonIndent: Boolean;
  61. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  62. fLastSaved : TDateTime;
  63. public
  64. constructor Create; virtual;
  65. {$IF CompilerVersion >= 32.0}[JsonIgnoreAttribute]{$ENDIF}
  66. property OnApplyConfig : TApplyConfigEvent read fOnApplyConfig write fOnApplyConfig;
  67. {$IF CompilerVersion >= 32.0}[JsonIgnoreAttribute]{$ENDIF}
  68. property DateTimeZone : TDateTimeZone read fDateTimeZone write fDateTimeZone;
  69. {$IF CompilerVersion >= 32.0}[JsonIgnoreAttribute]{$ENDIF}
  70. property JsonIndent : Boolean read fJsonIndent write fJsonIndent;
  71. {$IF CompilerVersion >= 32.0}[JsonIgnoreAttribute]{$ENDIF}
  72. property LastSaved : TDateTime read fLastSaved write fLastSaved;
  73. procedure Apply;
  74. procedure DefaultValues; virtual;
  75. function ToJSON : string;
  76. procedure FromJSON(const json : string);
  77. end;
  78. {Usage: create a descend class from TAppConfig and add public properties to be loaded/saved
  79. TMyConfig = class(TAppConfig)
  80. private
  81. fName : string;
  82. fSurname : string;
  83. fStatus : Integer;
  84. public
  85. property Name : string read fName write fName;
  86. property SurName : string read fSurname write fSurname;
  87. property Status : Integer read fStatus write fStatus;
  88. end;
  89. AppConfigProvider := TAppConfigJsonProvider<TMyConfig>.Create(MyConfig);
  90. MyConfig.Name := 'John';
  91. }
  92. implementation
  93. { TAppConfigProviderBase }
  94. constructor TAppConfigProviderBase<T>.Create(var cConfig : T);
  95. begin
  96. fCreateIfNotExists := True;
  97. //create object with rtti
  98. if Assigned(cConfig) then cConfig.Free;
  99. cConfig := InitObject;
  100. end;
  101. function TAppConfigProviderBase<T>.InitObject : T;
  102. var
  103. AValue: TValue;
  104. ctx: TRttiContext;
  105. f : TRttiField;
  106. rType: TRttiType;
  107. AMethCreate: TRttiMethod;
  108. begin
  109. ctx := TRttiContext.Create;
  110. try
  111. rType := ctx.GetType(TypeInfo(T));
  112. for AMethCreate in rType.GetMethods do
  113. begin
  114. if (AMethCreate.IsConstructor) and (Length(AMethCreate.GetParameters) = 0) then
  115. begin
  116. AValue := AMethCreate.Invoke(rType.AsInstance.AsInstance.MetaclassType,[]);
  117. Result := AValue.AsType<T>;
  118. Break;
  119. end;
  120. end;
  121. finally
  122. ctx.Free;
  123. end;
  124. end;
  125. { TAppConfig }
  126. constructor TAppConfig.Create;
  127. begin
  128. fDateTimeZone := TDateTimeZone.tzLocal;
  129. fJsonIndent := True;
  130. fLastSaved := 0;
  131. end;
  132. procedure TAppConfig.Apply;
  133. begin
  134. if Assigned(fOnApplyConfig) then fOnApplyConfig;
  135. end;
  136. procedure TAppConfig.DefaultValues;
  137. begin
  138. //inherit to set default values if no config exists before
  139. end;
  140. function TAppConfig.ToJSON : string;
  141. {$IF CompilerVersion >= 32.0}
  142. var
  143. Serializer : TJsonSerializer;
  144. {$ENDIF}
  145. begin
  146. Result := '';
  147. try
  148. {$IF CompilerVersion >= 32.0}
  149. Serializer := TJsonSerializer.Create;
  150. try
  151. Serializer.Formatting := TJsonFormatting.Indented;
  152. if JsonIndent then Serializer.Formatting := TJsonFormatting.Indented;
  153. if DateTimeZone = TDateTimeZone.tzLocal then
  154. begin
  155. Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Local;
  156. Serializer.DateFormatHandling := TJsonDateFormatHandling.FormatSettings;
  157. end
  158. else Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Utc;
  159. Result := Serializer.Serialize<TObject>(Self);
  160. finally
  161. Serializer.Free;
  162. end;
  163. {$ELSE}
  164. Result := TJson.ObjectToJsonString(Self);
  165. {$ENDIF}
  166. except
  167. on e : Exception do raise Exception.Create(e.Message);
  168. end;
  169. end;
  170. procedure TAppConfig.FromJSON(const json : string);
  171. {$IF CompilerVersion >= 32.0}
  172. var
  173. Serializer : TJsonSerializer;
  174. {$ENDIF}
  175. begin
  176. try
  177. {$IF CompilerVersion >= 32.0}
  178. Serializer := TJsonSerializer.Create;
  179. try
  180. Serializer.Formatting := TJsonFormatting.Indented;
  181. if JsonIndent then Serializer.Formatting := TJsonFormatting.Indented;
  182. if DateTimeZone = TDateTimeZone.tzLocal then
  183. begin
  184. Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Local;
  185. Serializer.DateFormatHandling := TJsonDateFormatHandling.FormatSettings;
  186. end
  187. else Serializer.DateTimeZoneHandling := TJsonDateTimeZoneHandling.Utc;
  188. Self := Serializer.Deserialize<TAppConfig>(json);
  189. finally
  190. Serializer.Free;
  191. end;
  192. {$ELSE}
  193. TJson.JsonToObject(Self,TJSONObject(TJSONObject.ParseJSONValue(json.Text)));
  194. {$ENDIF}
  195. except
  196. on e : Exception do raise Exception.Create(e.Message);
  197. end;
  198. end;
  199. end.