Mega Code Archive

 
Categories / Delphi / OOP
 

How to get the published properties of an persistent object

Title: How to get the published properties of an persistent object Question: 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; That's it ---- actually easy , or? best regards Boris Benjamin Wittfoth