Quick.RTTI.Utils.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. { ***************************************************************************
  2. Copyright (c) 2016-2020 Kike Pérez
  3. Unit : Quick.RTTI.Utils
  4. Description : Files functions
  5. Author : Kike Pérez
  6. Version : 1.4
  7. Created : 09/03/2018
  8. Modified : 14/07/2020
  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.RTTI.Utils;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. SysUtils,
  26. Quick.Commons,
  27. TypInfo,
  28. Rtti;
  29. type
  30. TRttiPropertyOrder = (roFirstBase, roFirstInherited);
  31. TRTTI = class
  32. private class var
  33. fCtx : TRttiContext;
  34. public
  35. {$IFNDEF FPC}
  36. class constructor Create;
  37. class destructor Destroy;
  38. class function GetField(aInstance : TObject; const aFieldName : string) : TRttiField; overload;
  39. class function GetField(aTypeInfo : Pointer; const aFieldName : string) : TRttiField; overload;
  40. class function FieldExists(aTypeInfo : Pointer; const aFieldName : string) : Boolean;
  41. class function GetFieldValue(aInstance : TObject; const aFieldName : string) : TValue; overload;
  42. class function GetFieldValue(aTypeInfo : Pointer; const aFieldName: string) : TValue; overload;
  43. {$ENDIF}
  44. class function GetProperties(aType : TRttiType; aOrder : TRttiPropertyOrder = roFirstBase) : TArray<TRttiProperty>;
  45. class function GetType(aTypeInfo : Pointer) : TRttiType;
  46. class function GetProperty(aInstance : TObject; const aPropertyName : string) : TRttiProperty; overload;
  47. class function GetProperty(aTypeInfo : Pointer; const aPropertyName : string) : TRttiProperty; overload;
  48. class function GetPropertyPath(aInstance : TObject; const aPropertyPath : string) : TRttiProperty;
  49. {$IFNDEF FPC}
  50. class function GetMemberPath(aInstance: TObject; const aPropertyPath: string): TRttiMember;
  51. {$ENDIF}
  52. class function PathExists(aInstance: TObject; const aPropertyPath: string) : Boolean;
  53. class function GetPathValue(aInstance : TObject; const aPropertyPath : string) : TValue;
  54. class procedure SetPathValue(aInstance: TObject; const aPropertyPath: string; aValue : TValue);
  55. class procedure SetPropertyValue(aInstance : TObject; const aPropertyName : string; aValue : TValue);
  56. class function PropertyExists(aTypeInfo : Pointer; const aPropertyName : string) : Boolean;
  57. class function GetPropertyValue(aInstance : TObject; const aPropertyName : string) : TValue; overload;
  58. class function GetPropertyValue(aTypeInfo : Pointer; const aPropertyName : string) : TValue; overload;
  59. class function GetPropertyValueEx(aInstance: TObject; const aPropertyName: string): TValue;
  60. {$IFNDEF FPC}
  61. class function FindClass(const aClassName: string): TClass;
  62. class function CreateInstance<T>: T; overload;
  63. class function CreateInstance(aBaseClass : TClass): TObject; overload;
  64. class function CallMethod(aObject : TObject; const aMethodName : string; aParams : array of TValue) : TValue;
  65. {$ENDIF}
  66. end;
  67. ERTTIError = class(Exception);
  68. TArrayHelper<T> = class
  69. public
  70. class function Concat(const Args: array of TArray<T>): TArray<T>; static;
  71. end;
  72. implementation
  73. { TRTTIUtils }
  74. {$IFNDEF FPC}
  75. class constructor TRTTI.Create;
  76. begin
  77. fCtx := TRttiContext.Create;
  78. end;
  79. class function TRTTI.CreateInstance<T>: T;
  80. var
  81. value: TValue;
  82. rtype: TRttiType;
  83. rmethod: TRttiMethod;
  84. rinstype: TRttiInstanceType;
  85. begin
  86. rtype := fCtx.GetType(TypeInfo(T));
  87. for rmethod in rtype.GetMethods do
  88. begin
  89. if (rmethod.IsConstructor) and (Length(rmethod.GetParameters) = 0) then
  90. begin
  91. rinstype := rtype.AsInstance;
  92. value := rmethod.Invoke(rinstype.MetaclassType,[]);
  93. Result := value.AsType<T>;
  94. Exit;
  95. end;
  96. end;
  97. end;
  98. class function TRTTI.CreateInstance(aBaseClass : TClass): TObject;
  99. var
  100. value: TValue;
  101. rtype: TRttiType;
  102. rmethod: TRttiMethod;
  103. rinstype: TRttiInstanceType;
  104. begin
  105. Result := nil;
  106. rtype := fCtx.GetType(aBaseClass);
  107. for rmethod in rtype.GetMethods do
  108. begin
  109. if (rmethod.IsConstructor) and (Length(rmethod.GetParameters) = 0) then
  110. begin
  111. rinstype := rtype.AsInstance;
  112. value := rmethod.Invoke(rinstype.MetaclassType,[]);
  113. Result := value.AsType<TObject>;
  114. Exit;
  115. end;
  116. end;
  117. end;
  118. class function TRTTI.CallMethod(aObject : TObject; const aMethodName : string; aParams : array of TValue) : TValue;
  119. var
  120. rtype : TRttiType;
  121. rmethod : TRttiMethod;
  122. rinstype: TRttiInstanceType;
  123. value : TValue;
  124. begin
  125. rtype := fCtx.GetType(aObject.ClassInfo);
  126. for rmethod in rtype.GetMethods do
  127. begin
  128. if CompareText(rmethod.Name,aMethodName) = 0 then
  129. begin
  130. rinstype := rtype.AsInstance;
  131. value := rmethod.Invoke(rinstype.MetaclassType,aParams);
  132. end;
  133. end;
  134. end;
  135. class destructor TRTTI.Destroy;
  136. begin
  137. fCtx.Free;
  138. end;
  139. class function TRTTI.FieldExists(aTypeInfo: Pointer; const aFieldName: string): Boolean;
  140. var
  141. rtype : TRttiType;
  142. begin
  143. rtype := fCtx.GetType(aTypeInfo);
  144. Result := rtype.GetField(aFieldName) <> nil;
  145. end;
  146. class function TRTTI.GetField(aInstance: TObject; const aFieldName: string): TRttiField;
  147. var
  148. rtype : TRttiType;
  149. begin
  150. Result := nil;
  151. rtype := fCtx.GetType(aInstance.ClassInfo);
  152. if rtype <> nil then
  153. begin
  154. Result := rtype.GetField(aFieldName);
  155. end;
  156. end;
  157. class function TRTTI.GetField(aTypeInfo: Pointer; const aFieldName: string): TRttiField;
  158. var
  159. rtype : TRttiType;
  160. begin
  161. Result := nil;
  162. rtype := fCtx.GetType(aTypeInfo);
  163. if rtype <> nil then
  164. begin
  165. Result := rtype.GetField(aFieldName);
  166. end;
  167. end;
  168. class function TRTTI.GetFieldValue(aInstance : TObject; const aFieldName: string): TValue;
  169. var
  170. rfield: TRttiField;
  171. begin
  172. rfield := GetField(aInstance,aFieldName);
  173. if rfield <> nil then Result := rfield.GetValue(aInstance);
  174. end;
  175. class function TRTTI.GetFieldValue(aTypeInfo : Pointer; const aFieldName: string): TValue;
  176. var
  177. rfield: TRttiField;
  178. begin
  179. rfield := GetField(aTypeInfo,aFieldName);
  180. if rfield <> nil then rfield.GetValue(aTypeInfo);
  181. end;
  182. {$ENDIF}
  183. class function TRTTI.GetProperty(aInstance: TObject; const aPropertyName: string): TRttiProperty;
  184. var
  185. rtype : TRttiType;
  186. begin
  187. Result := nil;
  188. rtype := fCtx.GetType(aInstance.ClassInfo);
  189. if rtype <> nil then Result := rtype.GetProperty(aPropertyName);
  190. end;
  191. class function TArrayHelper<T>.Concat(const Args: array of TArray<T>): TArray<T>;
  192. var
  193. i, j, out, len: Integer;
  194. begin
  195. len := 0;
  196. for i := 0 to High(Args) do
  197. len := len + Length(Args[i]);
  198. SetLength(Result, len);
  199. out := 0;
  200. for i := 0 to High(Args) do
  201. for j := 0 to High(Args[i]) do
  202. begin
  203. Result[out] := Args[i][j];
  204. Inc(out);
  205. end;
  206. end;
  207. class function TRTTI.GetProperties(aType: TRttiType; aOrder: TRttiPropertyOrder = roFirstBase): TArray<TRttiProperty>;
  208. var
  209. flat: TArray<TArray<TRttiProperty>>;
  210. t: TRttiType;
  211. depth: Integer;
  212. begin
  213. if aOrder = TRttiPropertyOrder.roFirstBase then
  214. begin
  215. t := aType;
  216. depth := 0;
  217. while t <> nil do
  218. begin
  219. Inc(depth);
  220. t := t.BaseType;
  221. end;
  222. SetLength(flat, depth);
  223. t := aType;
  224. while t <> nil do
  225. begin
  226. Dec(depth);
  227. {$IFNDEF FPC}
  228. flat[depth] := t.GetDeclaredProperties;
  229. {$ELSE}
  230. flat[depth] := t.GetProperties;
  231. {$ENDIF}
  232. t := t.BaseType;
  233. end;
  234. end
  235. else
  236. begin
  237. t := aType;
  238. depth := 0;
  239. while t <> nil do
  240. begin
  241. Inc(depth);
  242. t := t.BaseType;
  243. end;
  244. SetLength(flat, depth);
  245. t := aType;
  246. depth := 0;
  247. while t <> nil do
  248. begin
  249. {$IFNDEF FPC}
  250. flat[depth] := t.GetDeclaredProperties;
  251. {$ELSE}
  252. flat[depth] := t.GetProperties;
  253. {$ENDIF}
  254. Inc(depth);
  255. t := t.BaseType;
  256. end;
  257. end;
  258. Result := TArrayHelper<TRttiProperty>.Concat(flat);
  259. end;
  260. class function TRTTI.GetProperty(aTypeInfo: Pointer; const aPropertyName: string): TRttiProperty;
  261. var
  262. rtype : TRttiType;
  263. begin
  264. Result := nil;
  265. rtype := fCtx.GetType(aTypeInfo);
  266. if rtype <> nil then Result := rtype.GetProperty(aPropertyName);
  267. end;
  268. class function TRTTI.GetPropertyPath(aInstance: TObject; const aPropertyPath: string): TRttiProperty;
  269. var
  270. prop : TRttiProperty;
  271. proppath : string;
  272. propname : string;
  273. i : Integer;
  274. value : TValue;
  275. rtype : TRttiType;
  276. {$IFNDEF FPC}
  277. rfield : TRttiField;
  278. {$ENDIF}
  279. lastsegment : Boolean;
  280. begin
  281. Result := nil;
  282. proppath := aPropertyPath;
  283. lastsegment := False;
  284. rtype := fCtx.GetType(aInstance.ClassType);
  285. repeat
  286. i := proppath.IndexOf('.');
  287. if i > -1 then
  288. begin
  289. propname := Copy(proppath,1,i);
  290. Delete(proppath,1,i+1);
  291. end
  292. else
  293. begin
  294. propname := proppath;
  295. lastsegment := True;
  296. end;
  297. if rtype.TypeKind = TTypeKind.tkRecord then
  298. begin
  299. {$IFNDEF FPC}
  300. rfield := rtype.GetField(propname);
  301. if rfield <> nil then value := rfield.GetValue(aInstance);
  302. {$ELSE}
  303. raise ERTTIError.Create('FPC not supports record fields in RTTI');
  304. {$ENDIF}
  305. end
  306. else
  307. begin
  308. prop := rtype.GetProperty(propname);
  309. if prop = nil then Exit;
  310. if lastsegment then Exit(prop)
  311. else value := prop.GetValue(aInstance);
  312. end;
  313. if not lastsegment then
  314. begin
  315. if value.Kind = TTypeKind.tkClass then rType := fCtx.GetType(value.AsObject.ClassType)
  316. else if value.Kind = TTypeKind.tkRecord then rtype := fCtx.GetType(value.TypeInfo);
  317. end;
  318. until lastsegment;
  319. Result := nil;
  320. end;
  321. {$IFNDEF FPC}
  322. class function TRTTI.GetMemberPath(aInstance: TObject; const aPropertyPath: string): TRttiMember;
  323. var
  324. prop : TRttiProperty;
  325. proppath : string;
  326. propname : string;
  327. i : Integer;
  328. value : TValue;
  329. rtype : TRttiType;
  330. {$IFNDEF FPC}
  331. rfield : TRttiField;
  332. {$ENDIF}
  333. lastsegment : Boolean;
  334. begin
  335. Result := nil;
  336. proppath := aPropertyPath;
  337. lastsegment := False;
  338. rtype := fCtx.GetType(aInstance.ClassType);
  339. repeat
  340. i := proppath.IndexOf('.');
  341. if i > -1 then
  342. begin
  343. propname := Copy(proppath,1,i);
  344. Delete(proppath,1,i+1);
  345. end
  346. else
  347. begin
  348. propname := proppath;
  349. lastsegment := True;
  350. end;
  351. if rtype.TypeKind = TTypeKind.tkRecord then
  352. begin
  353. {$IFNDEF FPC}
  354. rfield := rtype.GetField(propname);
  355. if rfield <> nil then
  356. begin
  357. if lastsegment then Exit(rfield)
  358. else value := rfield.GetValue(value.GetReferenceToRawData);
  359. end;
  360. {$ELSE}
  361. raise ERTTIError.Create('FPC not supports record fields in RTTI');
  362. {$ENDIF}
  363. end
  364. else
  365. begin
  366. prop := rtype.GetProperty(propname);
  367. if prop = nil then Exit;
  368. if lastsegment then Exit(prop)
  369. else value := prop.GetValue(aInstance);
  370. end;
  371. if not lastsegment then
  372. begin
  373. if value.Kind = TTypeKind.tkClass then rType := fCtx.GetType(value.AsObject.ClassType)
  374. else if value.Kind = TTypeKind.tkRecord then rtype := fCtx.GetType(value.TypeInfo);
  375. end;
  376. until lastsegment;
  377. end;
  378. {$ENDIF}
  379. class function TRTTI.PathExists(aInstance: TObject; const aPropertyPath: string) : Boolean;
  380. var
  381. proppath : string;
  382. propname : string;
  383. i : Integer;
  384. value : TValue;
  385. rtype : TRttiType;
  386. rprop : TRttiProperty;
  387. {$IFNDEF FPC}
  388. rfield : TRttiField;
  389. {$ENDIF}
  390. lastsegment : Boolean;
  391. begin
  392. if not Assigned(aInstance) then Exit(False);
  393. lastsegment := False;
  394. proppath := aPropertyPath;
  395. rtype := fCtx.GetType(aInstance.ClassType);
  396. repeat
  397. Result := False;
  398. i := proppath.IndexOf('.');
  399. if i > -1 then
  400. begin
  401. propname := Copy(proppath,1,i);
  402. Delete(proppath,1,i+1);
  403. end
  404. else
  405. begin
  406. propname := proppath;
  407. lastsegment := True;
  408. end;
  409. if rtype.TypeKind = TTypeKind.tkRecord then
  410. begin
  411. {$IFNDEF FPC}
  412. rfield := rtype.GetField(propname);
  413. if rfield = nil then Exit
  414. else
  415. begin
  416. value := rfield.GetValue(value.GetReferenceToRawData);
  417. Result := True;
  418. end;
  419. {$ELSE}
  420. raise ERTTIError.Create('FPC not supports record fields in RTTI');
  421. {$ENDIF}
  422. end
  423. else
  424. begin
  425. rprop := rtype.GetProperty(propname);
  426. if rprop = nil then Exit
  427. else
  428. begin
  429. value := rprop.GetValue(aInstance);
  430. Result := True;
  431. end;
  432. end;
  433. if not lastsegment then
  434. begin
  435. if value.Kind = TTypeKind.tkClass then rType := fCtx.GetType(value.AsObject.ClassType)
  436. else if value.Kind = TTypeKind.tkRecord then rtype := fCtx.GetType(value.TypeInfo);
  437. end;
  438. until lastsegment;
  439. end;
  440. class function TRTTI.GetPathValue(aInstance: TObject; const aPropertyPath: string): TValue;
  441. var
  442. proppath : string;
  443. propname : string;
  444. i : Integer;
  445. value : TValue;
  446. rtype : TRttiType;
  447. rprop : TRttiProperty;
  448. {$IFNDEF FPC}
  449. rfield : TRttiField;
  450. {$ENDIF}
  451. lastsegment : Boolean;
  452. begin
  453. Result := nil;
  454. if not Assigned(aInstance) then Exit;
  455. lastsegment := False;
  456. proppath := aPropertyPath;
  457. rtype := fCtx.GetType(aInstance.ClassType);
  458. {$IFDEF FPC}
  459. value := aInstance;
  460. {$ENDIF}
  461. repeat
  462. i := proppath.IndexOf('.');
  463. if i > -1 then
  464. begin
  465. propname := Copy(proppath,1,i);
  466. Delete(proppath,1,i+1);
  467. end
  468. else
  469. begin
  470. propname := proppath;
  471. lastsegment := True;
  472. end;
  473. if rtype.TypeKind = TTypeKind.tkRecord then
  474. begin
  475. {$IFNDEF FPC}
  476. rfield := rtype.GetField(propname);
  477. if rfield = nil then raise ERTTIError.CreateFmt('Field "%s" not found in record',[propname])
  478. else value := rfield.GetValue(value.GetReferenceToRawData);
  479. {$ELSE}
  480. raise ERTTIError.Create('FPC not supports record fields in RTTI');
  481. {$ENDIF}
  482. end
  483. else
  484. begin
  485. rprop := rtype.GetProperty(propname);
  486. if rprop = nil then raise ERTTIError.CreateFmt('Property "%s" not found in object',[propname])
  487. {$IFNDEF FPC}
  488. else value := rprop.GetValue(aInstance);
  489. {$ELSE}
  490. else
  491. begin
  492. if rprop.PropertyType.IsInstance then value := GetObjectProp(value.AsObject,propname)
  493. else value := rprop.GetValue(value.AsObject);
  494. end;
  495. {$ENDIF}
  496. end;
  497. if not lastsegment then
  498. begin
  499. if value.Kind = TTypeKind.tkClass then rType := fCtx.GetType(value.AsObject.ClassType)
  500. else if value.Kind = TTypeKind.tkRecord then rtype := fCtx.GetType(value.TypeInfo);
  501. end;
  502. until lastsegment;
  503. Result := value;
  504. end;
  505. class procedure TRTTI.SetPathValue(aInstance: TObject; const aPropertyPath: string; aValue : TValue);
  506. var
  507. proppath : string;
  508. propname : string;
  509. i : Integer;
  510. value : TValue;
  511. rtype : TRttiType;
  512. rprop : TRttiProperty;
  513. {$IFNDEF FPC}
  514. rfield : TRttiField;
  515. {$ENDIF}
  516. lastsegment : Boolean;
  517. begin
  518. if not Assigned(aInstance) then Exit;
  519. lastsegment := False;
  520. proppath := aPropertyPath;
  521. rtype := fCtx.GetType(aInstance.ClassType);
  522. repeat
  523. i := proppath.IndexOf('.');
  524. if i > -1 then
  525. begin
  526. propname := Copy(proppath,1,i);
  527. Delete(proppath,1,i+1);
  528. end
  529. else
  530. begin
  531. propname := proppath;
  532. lastsegment := True;
  533. end;
  534. if rtype.TypeKind = TTypeKind.tkRecord then
  535. begin
  536. {$IFNDEF FPC}
  537. rfield := rtype.GetField(propname);
  538. if rfield = nil then raise ERTTIError.CreateFmt('Field "%s" not found in record',[propname])
  539. else
  540. begin
  541. if lastsegment then rfield.SetValue(value.GetReferenceToRawData,aValue)
  542. else value := rfield.GetValue(value.GetReferenceToRawData);
  543. end;
  544. {$ELSE}
  545. raise ERTTIError.Create('FPC not supports record fields in RTTI');
  546. {$ENDIF}
  547. end
  548. else
  549. begin
  550. rprop := rtype.GetProperty(propname);
  551. if rprop = nil then raise ERTTIError.CreateFmt('Property "%s" not found in object',[propname])
  552. else
  553. begin
  554. if lastsegment then rprop.SetValue(aInstance,aValue)
  555. else value := rprop.GetValue(aInstance);
  556. end;
  557. end;
  558. if not lastsegment then
  559. begin
  560. if value.Kind = TTypeKind.tkClass then rType := fCtx.GetType(value.AsObject.ClassType)
  561. else if value.Kind = TTypeKind.tkRecord then rtype := fCtx.GetType(value.TypeInfo);
  562. end;
  563. until lastsegment;
  564. end;
  565. class function TRTTI.GetPropertyValue(aInstance: TObject; const aPropertyName: string): TValue;
  566. var
  567. rprop : TRttiProperty;
  568. begin
  569. rprop := GetProperty(aInstance,aPropertyName);
  570. if rprop <> nil then
  571. begin
  572. {$IFNDEF FPC}
  573. Result := rprop.GetValue(aInstance);
  574. {$ELSE}
  575. if rprop.PropertyType.IsInstance then Result := GetObjectProp(aInstance,aPropertyName)
  576. else Result := rprop.GetValue(aInstance);
  577. {$ENDIF}
  578. end;
  579. end;
  580. class function TRTTI.GetPropertyValue(aTypeInfo: Pointer; const aPropertyName: string): TValue;
  581. var
  582. rprop : TRttiProperty;
  583. begin
  584. rprop := GetProperty(aTypeInfo,aPropertyName);
  585. if rprop <> nil then
  586. begin
  587. {$IFNDEF FPC}
  588. Result := rprop.GetValue(aTypeInfo);
  589. {$ELSE}
  590. if rprop.PropertyType.IsInstance then Result := GetObjectProp(aTypeInfo,aPropertyName)
  591. else Result := rprop.GetValue(aTypeInfo);
  592. {$ENDIF}
  593. end;
  594. end;
  595. class function TRTTI.GetPropertyValueEx(aInstance: TObject; const aPropertyName: string): TValue;
  596. var
  597. pinfo : PPropInfo;
  598. begin
  599. Result := nil;
  600. pinfo := GetPropInfo(aInstance,aPropertyName);
  601. if pinfo = nil then
  602. begin
  603. //if not found can be a public property
  604. Result := GetPropertyValue(aInstance,aPropertyName);
  605. Exit;
  606. end;
  607. case pinfo.PropType^.Kind of
  608. tkInteger : Result := GetOrdProp(aInstance,pinfo);
  609. tkInt64 : Result := GetInt64Prop(aInstance,aPropertyName);
  610. tkFloat : Result := GetFloatProp(aInstance,aPropertyName);
  611. tkChar : Result := Char(GetOrdProp(aInstance,aPropertyName));
  612. {$IFDEF FPC}
  613. tkWString : Result := GetWideStrProp(aInstance,aPropertyName);
  614. tkSString,
  615. tkAString,
  616. {$ELSE}
  617. tkUString,
  618. tkWString,
  619. {$ENDIF}
  620. tkLString : Result := GetStrProp(aInstance,pinfo);
  621. {$IFDEF FPC}
  622. tkEnumeration :Result := GetOrdProp(aInstance,aPropertyName);
  623. {$ELSE}
  624. tkEnumeration : Result := GetOrdProp(aInstance,aPropertyName);
  625. {$ENDIF}
  626. tkSet : Result := GetSetProp(aInstance,pinfo,True);
  627. {$IFNDEF FPC}
  628. tkClass :
  629. {$ELSE}
  630. tkBool : Result := Boolean(GetOrdProp(aInstance,pinfo));
  631. tkObject :
  632. {$ENDIF} Result := GetObjectProp(aInstance,pinfo);
  633. tkDynArray : Result := GetDynArrayProp(aInstance,pinfo);
  634. end;
  635. end;
  636. class function TRTTI.GetType(aTypeInfo: Pointer): TRttiType;
  637. begin
  638. Result := fCtx.GetType(aTypeInfo);
  639. end;
  640. class function TRTTI.PropertyExists(aTypeInfo: Pointer; const aPropertyName: string) : Boolean;
  641. var
  642. rtype : TRttiType;
  643. begin
  644. Result := False;
  645. rtype := fCtx.GetType(aTypeInfo);
  646. if rtype <> nil then Result := rtype.GetProperty(aPropertyName) <> nil;
  647. end;
  648. class procedure TRTTI.SetPropertyValue(aInstance: TObject; const aPropertyName: string; aValue: TValue);
  649. var
  650. rprop : TRttiProperty;
  651. begin
  652. rprop := GetProperty(aInstance,aPropertyName);
  653. if rprop <> nil then rprop.SetValue(aInstance,aValue);
  654. end;
  655. {$IFNDEF FPC}
  656. class function TRTTI.FindClass(const aClassName: string): TClass;
  657. var
  658. rType : TRttiType;
  659. rList : TArray<TRttiType>;
  660. begin
  661. Result := nil;
  662. rList := fCtx.GetTypes;
  663. for rType in rList do
  664. begin
  665. if (rType.IsInstance) and (aClassName.EndsWith(rType.Name)) then
  666. begin
  667. Result := rType.AsInstance.MetaClassType;
  668. Break;
  669. end;
  670. end;
  671. end;
  672. {$ENDIF}
  673. end.