Quick.RTTI.Utils.pas 20 KB

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