Archived

This topic is now archived and is closed to further replies.

czar

ittirating through record fields

Recommended Posts

I have this situation where I would like to run through the fields of my record and set all the integer types to zero. At the moment I am doing the following type TStock = record wood : integer; stone : integer; grain : integer; end; == stock is type Tstock == stock.stone := 0; stock.grain := 0; etc There must be a more elegant way. The stock type is going to increase and there must be a way that I can run through an unknown amount of fields programmatically. I have tried searching on dejanews but I don''t even know the terminology for what I am trying to achieve so I just run into blind alleys. Can anyone point in me in the right direction with some pointers, code, terminology or URLs where I can get more info? help is much regarded.

Share this post


Link to post
Share on other sites
sweet. Thats works nicely.

Just another question is there a way to tell what type each field is? i.e. say that Tstock was

type TStock = record
grain : integer;
flour : integer;
NameofBuilding : string;

What would I need to do if I only wanted to do some operation with the integers but I want to leave the string(s) alone? Can that be done? If so how? I had a play around with the code that LifePower provided but I couldn't get it to stop reseting NameOfBuilding.

==============

Coupled with this is the question is it possible to return the name of the field?

For example if I do the following,

for i:= 0 to SizeOf(TStock) -1 do

I would like to grab the name/label of each field. Then it would be possible for me to print on the screen the contents of the fields without having to know the name of each field. i.e.

The current stock contained in the "nameofBuilding" is
Current "grain" is "0"
Current "gold" is "20"

where the ".." is taken from the record.

I hope this doesn't sound too confusing, its just that an answer to question has a tendency to generate more questions

Ralph





[edited by - czar on July 30, 2002 6:01:28 PM]

Share this post


Link to post
Share on other sites
No such luck for when you add strings, dynamic arrays, or interfaces. Those are all referanced counted, and zeroing a reference in such a manner defeats the reference counting used by Delphi.

The only way to do the last part is to use RTTI for properties. To use RTTI you have toinclude the typinfo unit (helper routines to maniuplate properties). Make sure you add the Compiler directive {$TYPEINFO ON} before the class declaration.

Use "Function GetPropvalue(Instance : Tobject; const PropName : string; PreferStrings : boolean) : Variant"
Call this with PreferStrings as true(sets & enums get returned as strings), and assign the variant to a string variable to force its contents to be converted into a string.
There is also "Procedure SetPropValue(Instance : Tobject; const PropName : string; const value: Variant);"
Note: At runtime you can change the boolean Identifiers & the dot sperator (ie 1.5 -one point five).

To itterate through the list of properties you need to use
GetPropList or GetPropInfos;
In this example I will use option b).


    Type
TProperty = record
Name : string;
Value : string;
Kind : TTypeKind;
end;
TPropArray = array of TProperty;

Function GetProperties(Instance : Tobject;
AKinds : TTypeKinds = [tkString]) : TPropArray;
var
count,RealCount,Index : Integer;
p : PPropList;
PropInfo : PPropInfo;
begin
if (Instance = nil) or (Instance.ClassInfo = nil) then exit;
Count := GetTypeData(Instance.ClassInfo)^.PropCount;
if count = 0 then exit;
setLength(Result,count);
GetMem(p,Count * sizeof(pointer));
try
GetPropInfos(Instance.ClassInfo,p);
RealCount := 0;
For Index := pred(count) downto 0 do
begin
PropInfo := p^[index];
If PropInfo^.PropType^.Kind in AKinds then
begin
Result[RealCount].Name := PropInfo^.Name;
Result[RealCount].Kind := PropInfo^.PropType^.Kind;
Result[RealCount].Value := GetPropvalue(Instance,Result[RealCount].Name,true);
inc(RealCount);
end;
end;
SetLength(Result,RealCount);
finally
FreeMem(p);
end;
end; {GetProperties}

Procedure SetProperties(Instance : Tobject;const values : TPropArray);
var
Index : integer;
begin
if (Instance <> nil) and (values <> nil) then
For Index := High(values) downto 0 do
SetPropValue(Instance,values[index].name,values[index].value);
end; {SetProperties}

That _should_ work. I'm using a dynamic array as they are a much nicer way to wok with dynamic memory than manually allocated & deallocated arrays.


[edited by - ggs on July 31, 2002 2:26:17 AM]

Share this post


Link to post
Share on other sites