[ Pobierz całość w formacie PDF ]
.Name]));EnumName := GetEnumName(TypeInfo(TTypeKind), Integer(ClassTypeInfo.Kind));Add(Format('Typ: %s', [EnumName]));Add(Format('Rozmiar: %d', [AClass.InstanceSize]));Add(Format('Zdefiniowana w: %s.pas', [ClassTypeData.UnitName]));Add(Format('Liczba w³aœciwoœci: %d',[ClassTypeData.PropCount]));end;Zadaniem funkcji GetEnumName() jest zwrócenie identyfikatora odpowiadaj¹cegookreœlonej wartoœci typu wyliczeniowego; funkcja ta zdefiniowana jest w moduleTypInfo.Pas.Odtwarzanie genealogii obiektuTo zadanie jest w gruncie rzeczy nieskomplikowane i polega na posuwaniu siê wgórê listy coraz to starszych przodków obiektu — typ klasy macierzystej jestwynikiem metody ClassParent().Ca³a zabawa koñczy siê na próbie pobrania klasymacierzystej dla klasy TObject — czego wynikiem jest wartoœæ NIL.Nazwykolejnych klas macierzystych dodawane s¹ jako kolejne pozycje listy:AncestorClass := AClass.ClassParent;{ Iteracja wzwy¿ ³añcucha genealogicznego a¿ do osi¹gniecianajwy¿szej klasy bazowej}AStrings.Add('Genealogia klasy');while AncestorClass nil dobeginAStrings.Add(Format(' %s',[AncestorClass.ClassName]));AncestorClass := AncestorClass.ClassParent;end;Uzyskiwanie informacji o w³aœciwoœciach obiektuLiczbê w³aœciwoœci obiektu zawiera pole PropCount struktury TTypeData.Co dosamych w³aœciwoœci: istnieje kilka metod pobrania ich charakterystyki — myopiszemy tutaj dwie z nich.Uzyskanie charakterystyki w³aœciwoœci obiektu nale¿y do proceduryGetClassProperties().Po zidentyfikowaniu liczby w³aœciwoœci nastêpujeprzydzielenie pamiêci dla tablicy, której poszczególne elementy wskazywaæ bêd¹struktury identyfikuj¹ce poszczególne w³aœciwoœci:GetMem(PropList, SizeOf(PPropInfo) * ClassTypeData.PropCount);Zmienna Proplist jest wskaŸnikiem do nastêpuj¹cej tablicy:typeTPropList = array [ 0.16739] of PPropInfo;Ka¿dy element tej tablicy wskazuje natomiast na nastêpuj¹c¹ strukturê:TPropInfo = packed recordPropType: PPTypeInfo;GetProc: Pointer;SetProc: Pointer;StoredProc: Pointer;Index: Integer;Default: Longint;NameIndex: SmallInt;Name: ShortString;end;Wpisania informacji do tablicy dokonuje procedura GetPropInfos():GetPropInfos(AClass.ClassInfo, PropList);Analizuj¹c kolejne elementy tablicy, do³¹czamy charakterystykê poszczególnychw³aœciwoœci do wyœwietlanej listy, z pominiêciem jednak¿e w³aœciwoœcizdarzeniowych, bêd¹cych de facto wskaŸnikami do metod:for i := 0 to ClassTypeData.PropCount - 1 do// odrzuæ wszystkie w³aœciwoœci zdarzeniowe (czyli bêd¹ce wskaŸnikami// do metod – Kind=tkMethod)if not (PropList[i]^.PropType^.Kind = tkMethod)thenAStrings.Add(Format('%s: %s', [PropList[i]^.Name,PropList[i]^.PropType^.Name]));Innym sposobem wype³nienia tablicy charakterystyk¹ w³aœciwoœci wybranychkategorii jest wywo³anie funkcji GetPropList(); wykorzystamy j¹ do tego, abyuzupe³niæ listê w³aœciwoœciami zdarzeniowymi, które pominêliœmy w pierwszymkroku:NumProps := GetPropList(AClass.ClassInfo, [tkMethod], PropList);if NumProps 0 then beginAStrings.Add('');AStrings.Add('ZDARZENIA ================ ');AStrings.Add('');end;// Wpisz dane o w³aœciwoœciach zdarzeniowych na listê ³añcuchówfor i := 0 to NumProps - 1 doAStrings.Add(Format('%s: %s', [PropList[i]^.Name,PropList[i]^.PropType^.Name]));Wynikiem funkcji GetPropList() jest liczba w³aœciwoœci nale¿¹cych do kategoriiokreœlonej przez drugi parametr wywo³ania; je¿eli trzeci parametr, okreœlaj¹cylistê docelow¹ ma wartoœæ NIL, zwrócenie liczby w³aœciwoœci jest jedynymefektem dzia³ania procedury — umo¿liwia to przydzielenie wystarczaj¹cejpamiêci dla tablicy wynikowej, której wskaŸnik przekazany bêdzie przypowtórnym wywo³aniu.W opisywanym tu przyk³adzie nie ma takiego problemu, gdy¿rozmiar tablicy zawieraj¹cej wskaŸniki do struktur TPropInfo ustalany jest napodstawie ogólnej liczby w³aœciwoœci klasy.Reasumuj¹c — procedura GetPropInfos() jest u¿yteczna w sytuacji, gdy pobierasiê informacjê o wszystkich w³aœciwoœciach; je¿eli jednak interesuj¹ nas tylkow³aœciwoœci okreœlonych kategorii, wygodniejsza jest funkcja GetPropList().Sprawdzanie istnienia okreœlonej w³aœciwoœci w obiekcieNieco wczeœniej zwróciliœmy uwagê na problem rozró¿nienia pomiêdzy komponentamiwra¿liwymi na dane a pozosta³ymi komponentami formularza, informuj¹cjednoczeœnie, i¿ rozwi¹zanie tego problemu sprowadza siê do sprawdzaniaobecnoœci w³aœciwoœci DataSource w klasie komponentu.Sprawdzenie istnieniadanej w³aœciwoœci jest szczególnym przypadkiem odczytania jej charakterystyki,któr¹ to czynnoœæ wykonuje funkcja GetPropInfo():function GetPropInfo(TypeInfo: PTypeInfo; const PropName: string): PPropInfo;Jeœli w³aœciwoœæ o nazwie okreœlonej przez PropName nie istnieje w danejklasie, funkcja zwraca wartoœæ NIL.To natychmiast sugeruje rozwi¹zanieproblemu:Function IsDataAware(Acomponent: TComponent): Boolean;// funkcja sprawdza, czy komponent posiada w³aœciwoœæ// o nazwie DataSource zgodn¹ z typem TDataSourcevarPropInfo: PPropInfo;beginPropInfo := GetPropInfo(AComponent.ClassInfo, 'DataSource');Result := (PropInfo NIL);// dodatkowe testy zwiêkszaj¹ce wiarygodnoœæif Result Thenbeginif not ((PropInfo^.PropType^.Kind = tkClass)and(GetTypeData(PropInfo^.PropType^).ClassType.InheritsFrom(TDataSource)))ThenResut := FALSE;end;end;Oczywiœcie, sama nazwa w³aœciwoœci (DataSource) niczego jeszcze nie przes¹dza —wszak ka¿dy mo¿e zdefiniowaæ klasê opatruj¹c tak¹ nazw¹ w³aœciwoœæ — powiedzmy— ca³kowitoliczbow¹.Aby wiêc zwiêkszyæ wiarygodnoœæ funkcji IsDataAware(),dodatkowo sprawdza siê, czy w³aœciwoœæ o nazwie DataSource jest w³aœciwoœci¹obiektow¹ o typie zgodnym z typem TDataSource.Zaprezentowan¹ funkcjê mo¿na by uogólniæ na dowoln¹ w³aœciwoœæ dowolnej klasy:Function HasProperty(AComponent: TComponent; APropertyName:String):Boolean;varPropInfo: PPropInfo;beginPropInfo := GetPropInfo(AComponent
[ Pobierz całość w formacie PDF ]
Darmowy hosting zapewnia PRV.PL