2005. augusztus 9., kedd
Get the published properties of an persistent object
Problem/Question/Abstract:
How to get the published properties of an persistent object / Using the pPropInfo-Pointer and the RTTI of Delphi
Answer:
The TypeInfo unit of Delphi declares several types and functions that gives you easy access to the puplished properties of an object and other informations.
You can obtain a list of the published properties of a class and get the name an type of each property.
The TypeInfo funtion returns a pointer to a type information record. The TypInfo unit declares a real type, that is, a pointer to a TTypeInfo record :
PTypeInfo = ^TTypeInfo;
TTypeInfo = record
Kind: TTypeKind;
Name: ShortString;
end;
The TTypeKind datatype describes the Datatype , returned by the GetTypeData function.
TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat,
tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString,
tkVariant, tkArray, tkRecord, tkInterface, tkInt64, tkDynArray);
TTypeKinds = set of TTypeKind;
Well ... for our first step to access the objects published properties we need to use the PPropInfo-pointer.
PPropInfo = ^TPropInfo;
TPropInfo = packed record
PropType: PPTypeInfo;
GetProc: Pointer;
SetProc: Pointer;
StoredProc: Pointer;
Index: Integer;
Default: Longint;
NameIndex: SmallInt;
Name: ShortString;
end;
To clarify it, please take a look at this example :
function GetFontSize(Obj: TPersistent): Integer;
{
in this Procedure we want to get the pPropInfo-pointer - pointing
on the Font-Property from an arbitrary TPersistent-Class.
The return-value in this instance will be the font-size ( if the font
property exists , if not -> the return value will be -1 )
}
var
PropInfo: PPropInfo;
begin
RESULT := -1;
// Get the PPropInfo-Pointer for Font of the TPersistent obj
PropInfo := GetPropInfo(Obj, 'Font');
// At first we will find out if the property FONT exists
if PropInfo = nil then
EXIT; // The Property doesn't exists
{
TFont is not an ordinal-Type - therefore will have to control if
Typekind of the TypeInfo-Class is set to tkClass
}
if PropInfo.PropType^.Kind <> tkClass then
EXIT; // property isn't a tkClass type
{
now, we now that the TypeKind of die PropInfo-pointer is a class .
last but not least we will use the GetObjectProp, the return-value
of this function is a TObject. Subsequently, we will use this object as
a TFont to get the Size value.
}
RESULT := ((GetObjectProp(Obj, PropInfo)) as TFont).Size;
end;
But to get the complete list of all properties of a TPersistent-Class we will need the pPropList-Type . This type is a simple pointer-array and the magic key to all Property-Informations and their structures.
Take a look at this :
procedure TForm1.Button1Click(Sender: TObject);
const
tkOrdinal = [tkEnumeration, tkInteger, tkChar, tkSet, tkWChar]; //Filter
begin
{
in this method of the mainform-class we are seeking for all ordinal-type
properties of the edit1-component. The from the GetPropertyList method
returned list of all properties will be written into the Listbox1. You can
replace the obj parameter with an arbitrary TObject ( but usually TPersistent
objects ).
For another filter please take a look at the TTypeKinds-set.
}
GetPropertyList(Edit1, ListBox1.Items, tkOrdinal);
end;
procedure GetPropertyList(Obj: TObject; List: TStrings; Filter: TTypeKinds);
var
PropList: pPropList;
count, i: Integer;
begin
List.Clear;
// Here we'll get the count of the given properties, ...
Count := GetPropList(Obj.ClassInfo, Filter, nil);
// ...and create room for the PropList,...
GetMem(PropList, Count * SizeOf(PPropInfo));
// ...get the Proplist-Data,...
GetPropList(Obj.ClassInfo, Filter, PropList);
// ...and write the property-names into the StringList
for i := 0 to Count - 1 do
List.Add(Proplist[i].Name);
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése