delphi2010遍历rtti的记录

时间:2011-03-05 07:54:17

标签: delphi rtti

type
 myrec = record
 id:dWord;
 name:array[0..31] of  WideChar;
 three:dword;
 count:dword;
 ShuXing:Single;
 ShuXing2:dword;
 ShuXing3:dWORD;

  end;

var
  Form1: TForm1;
  mystr:TMemoryStream;
  nowmyrec:myrec;

implementation
 USES Rtti;
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);


var
  rttiContext: TRttiContext;
  rttiType: TRttiType;
  fields: TArray<TRttiField>;
  item: myrec;
  i:word;
begin
mystr:=TMemoryStream.Create;
mystr.LoadFromFile(ExtractFilePath(Application.exename)+'1.data');
mystr.Position:=20;
mystr.readbuffer(nowmyRec,88);




 rttiType := rttiContext.GetType(TypeInfo(myRec));
  fields := rttiType.GetFields;
   for i := low(fields) to high(fields) do
   begin
Memo1.Lines.Add(fields[i].GetValue(@nowmyRec).ToString );


   end;

end;

end.

myrec.name是中文字符,myrec.name的长度是64字节,我无法读取myrec.name到备忘录,请帮帮我!!!

1 个答案:

答案 0 :(得分:2)

我在Delphi 2010上,我发现你的代码存在一些问题。首先,我无法使用RTTI方法处理字符数组的内联声明。我改成了:

type
  TCharArray = array[0..31] of WideChar;
  TRec = record
    id:dWord;
    name:TCharArray;
  end;

如果以内联方式声明数组,那么对GetValue的调用会引发AV。这可能是在XE中修复的,或者很可能我错误地使用了RTTI。

其次,您需要对数组进行特殊处理而不是标量值:

procedure Main;
var
  i, j: Integer;
  rec: TRec;
  rttiContext: TRttiContext;
  rttiType: TRttiType;
  fields: TArray<TRttiField>;
  val: TValue;
  s: string;
begin
  rec.id := 1;
  rec.name := 'Hello Stack Overflow';

  rttiType := rttiContext.GetType(TypeInfo(TRec));
  fields := rttiType.GetFields;
  for i := low(fields) to high(fields) do begin
    val := fields[i].GetValue(@rec);
    if val.IsArray then begin
      s := '';
      for j := 0 to val.GetArrayLength-1 do begin
        s := s+val.GetArrayElement(j).ToString;
      end;
      Writeln(s);
    end else begin
      Writeln(val.ToString);
    end;
  end;
end;

输出:

1
Hello Stack Overflow

这显然不是生产代码,但它至少应该让你回到路上!

P.S。这是我第一次看到新的RTTI功能。它看起来很漂亮!