Quick.RTTI.Utils.pas 19 KB

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