2005. augusztus 9., kedd

Get the published properties of an persistent object


How to get the published properties of an persistent object / Using the pPropInfo-Pointer and the RTTI of Delphi


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;

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;

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 )
  PropInfo: PPropInfo;
  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;

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);

  tkOrdinal = [tkEnumeration, tkInteger, tkChar, tkSet, tkWChar]; //Filter

    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);

procedure GetPropertyList(Obj: TObject; List: TStrings; Filter: TTypeKinds);
  PropList: pPropList;
  count, i: Integer;
  // 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

Nincsenek megjegyzések:

Megjegyzés küldése