vložil Radek Červinka
20. října 2010 23:43
Zkoušel jsem si hrát s RTTI (Run Time Type Information) a byl jsem tak nadšen jednoduchostí použití, že výsledkem je jednoduchý program, který ve stromě zobrazuje známé typy včetně metod, property a polí. Zároveň ukazuje efektivní použití anonymních metod, generických typů a to vše na 100 řádcích včetně deklarace.

Mějme formulář s TTreeView zarovnaným na celou plochu. V kódu formuláře bude následující kód.
1unit Unit1;
2
3interface
4
5uses
6 Forms, StdCtrls, ComCtrls, Classes, Controls, Generics.Defaults;
7
8type
9 TForm1 = class(TForm)
10 tv1: TTreeView;
11 procedure FormCreate(Sender: TObject);
12 private
13
14 procedure mFillTree;
15 public
16
17 end;
18
19var
20 Form1: TForm1;
21
22implementation
23
24
25
26uses
27 SysUtils, Rtti, Generics.Collections, TypInfo;
28
29procedure TForm1.FormCreate(Sender: TObject);
30begin
31 tv1.Items.BeginUpdate;
32 try
33 mFillTree;
34 finally
35 tv1.Items.EndUpdate;
36 end;
37end;
38
39procedure TForm1.mFillTree;
40var
41 ctx: TRttiContext;
42 t: TRttiType;
43 oNode, oTempNode: TTreeNode;
44 arTypes: TArray<Rtti.TRttiType>;
45 cmp:TDelegatedComparer<Rtti.TRttiType>;
46 arMethods: TArray<TRttiMethod>;
47 m: TRttiMethod;
48 p: TRttiProperty;
49 f: TRttiField;
50
51begin
52
53 ctx:= TRttiContext.Create;
54 try
55
56 arTypes := ctx.GetTypes;
57
58
59 cmp := TDelegatedComparer<Rtti.TRttiType>.Create(
60 function (const Left, Right: TRttiType): Integer
61 begin
62 Result := AnsiCompareStr(Left.QualifiedName, Right.QualifiedName);
63 end);
64
65
66 TArray.Sort<Rtti.TRttiType>(arTypes, cmp);
67 cmp.Free;
68
69
70 for t in arTypes do
71 begin
72
73 oNode:= tv1.Items.AddChild(nil, t.QualifiedName);
74
75
76 oTempNode := tv1.Items.AddChild(oNode, 'metody');
77 for m in t.GetMethods do
78 tv1.Items.AddChild(oTempNode, m.ToString);
79
80
81 oTempNode := tv1.Items.AddChild(oNode, 'property');
82 for p in t.GetProperties do
83 tv1.Items.AddChild(oTempNode, p.ToString);
84
85
86 oTempNode := tv1.Items.AddChild(oNode, 'pole');
87 for f in t.GetFields do
88 tv1.Items.AddChild(oTempNode, f.ToString);
89
90 end;
91 finally
92 ctx.Free;
93 end;
94end;
95
96end.
Pěkná konstrukce je od řádku 58, kdy používáme obecný porovnávač (jeden z několika možných), ale vlastní implementace porovnávání je pomocí anonymní metody.
Deklarace TDelegatedComparer je v jednotce Generics.Defaults a vypadá takto (TDelegatedComparer je jen jedna z možností):
1TComparison<T> = reference to function(const Left, Right: T): Integer;
2
3 TDelegatedComparer<T> = class(TComparer<T>)
4 private
5 FCompare: TComparison<T>;
6 public
7 constructor Create(const ACompare: TComparison<T>);
8 function Compare(const Left, Right: T): Integer; override;
9 end;
Zbytek kódu je podle mne jasný a přímočarý, případné dotazy do komentářů. Jo a pro kompilaci je nutné Delphi 2010 a vyšší.