Suite101

RTTI Part 3. Working with property's defaults.


© Lyapin Ilya

Each published property can have a default value. This value is stored as a part of the RTTI information. Delphi uses a default value of the property in order to determine whether the property value should be stored in the form file (*.DFM). The property is stored in the DFM file if its value is not equal to the default only. Delphi uses this in order to save space in the form file.

If a property is ordinal (integer, set, or enumeration) it's possible to define a default value. For all other properties the default is zero (an empty string for a siring property, 0.0 for floating point property, Nil value for a pointer).

The default value is applied when writing DFM - file only. An object's constructor should explicitly set the values of the object's properties to the default. See Listing 1.

TEnum=(enVal1, enVal2, enVal3);
TSet=set of TEnum;

TNewComponent = class( TComponent )
private
FCharProp: char;
FOrdProp: integer;
FEnumProp: TEnum;
FSetProp: TSet;
public
Constructor Create ( AOwner: TComponent); override;
published
property OrdProp : integer read FOrdProp write FOrdProp default 1000;
property CharProp : char read FCharProp write FCharProp default 'A';
property EnumProp : TEnum read FEnumProp write FEnumProp default enVal2;
property SetProp: TSet read FSetProp write FSetProp default [enVal2, enVal3];
end;
implementation
{ TNewComponent }
constructor TNewComponent.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCharProp := 'A';
FOrdProp:= 1000;
FEnumProp:= enVal2;
FSetProp:= [enVal2, enVal3];
end;

Listing 1.

The common error - programmer forget to initialize property in the constructor. Or may be he decides to change the default value later or to define new property...

RTTI allows getting the property type and its default value. So it's easy to write generic procedure that will set all properties values to the default value defined in the declaration. This procedure should be called in the first line of the constructor to make sure that all properties are correctly initialized. See Listing 2.

procedure SetPropertyDefaults(obj:TObject);
const
tkPropsWithDefault = [tkInteger, tkChar, tkSet, tkEnumeration];
NoDefault:integer=-1;
var
PropInfos:PPropList;
Count:Integer;
i:integer;
begin
count:=GetPropList(obj.ClassInfo,tkPropsWithDefault,nil);
PropInfos:=AllocMem(Count*sizeof(pPropInfo));
try
GetPropList(obj.ClassInfo,tkPropsWithDefault,PropInfos);
for i:=0 to count-1 do
if PropInfos[i]^.Default<>NoDefault then
SetOrdProp(obj,PropInfos[i],PropInfos[i]^.Default);
finally
FreeMem(PropInfos);
end;
end;

Listing 2.

Code explanation.

The const section defines tkPropsWithDefault constant that defines a set of all possible property types that could have a default value.

In the first line of code count variable is assigned to the number of object's properties using GetPropList function.

A call to AllocMem functions allocates memory for the list of properties and stores a pointer in the PropList variable.

A for loop iterates through the PropList array. Each property which default value is not equal to NoDefault constant is set to its default value with SetOrdProp procedure defined in typInfo.pas as
procedure SetOrdProp(Instance: TObject; PropInfo: PPropInfo;Value: Longint);

Go To Page: 1 2


The copyright of the article RTTI Part 3. Working with property's defaults. in Delphi Programming is owned by . Permission to republish RTTI Part 3. Working with property's defaults. in print or online must be granted by the author in writing.

Post this Article to facebook Add this Article to del.icio.us! Digg this Article furl this Article Add this Article to Reddit Add this Article to Technorati Add this Article to Newsvine Add this Article to Windows Live Add this Article to Yahoo Add this Article to StumbleUpon Add this Article to BlinkLists Add this Article to Spurl Add this Article to Google Add this Article to Ask Add this Article to Squidoo