【发布时间】:2013-02-20 12:32:42
【问题描述】:
我在尝试使用 Delphi 的 RTTI 访问指向记录数据中记录类型的指针时遇到了麻烦。
请检查我一直在处理的示例代码。
// Dummy Header
typDummyHeader = ^tysDummyHeader;
tysDummyHeader = record
MessageCode : Integer;
MessageLength : Integer;
end;
// Dummy record having header and trailer
tysDummyRecord = record
Header : tysDummyHeader;
BotAmount : Double;
SoldAmount : Double;
SoldQty : Int64;
BotQty : Int64;
Tailer : typDummyHeader; // pointer to Dummy Header
end;
TclDummy = class
class function GetFieldValue<T>(const pipInstance : Pointer;
const piclField : TRttiField) : string;
class function ParseAndReturnString<T>(piclObject : T) : string;
end;
var
frmRTTITest: TfrmRTTITest;
implementation
{$R *.dfm}
procedure TfrmRTTITest.FormCreate(Sender: TObject);
var
losDummyRecord : tysDummyRecord;
begin
FillChar(losDummyRecord, SizeOf(tysDummyRecord), #0);
losDummyRecord.Header.MessageCode := 5000;
losDummyRecord.Header.MessageLength := 54433;
losDummyRecord.BotAmount := 19.45;
losDummyRecord.SoldAmount := 34.22;
losDummyRecord.SoldQty := 102;
losDummyRecord.BotQty := 334;
losDummyRecord.Tailer := @losDummyRecord.Header;
ShowMessage(TclDummy.ParseAndReturnString<tysDummyRecord>(losDummyRecord));
end;
class function TclDummy.GetFieldValue<T>(const pipInstance : Pointer;
const piclField : TRttiField) : string;
begin
case piclField.FieldType.TypeKind of
tkFloat: Result := FloatToStr(piclField.GetValue(pipInstance).AsExtended);
tkInt64: Result := IntToStr(piclField.GetValue(pipInstance).AsInt64);
tkInteger: Result := IntToStr(piclField.GetValue(pipInstance).AsInteger);
tkString: Result := Trim(piclField.GetValue(pipInstance).AsString);
end;
end;
class function TclDummy.ParseAndReturnString<T>(piclObject : T) : string;
var
losContext : TRttiContext;
losContextType : TRttiType;
loclField : TRttiField;
losRecordRTTI : TRttiRecordType;
loclRecordField : TRttiField;
losPointerType : TRttiPointerType;
losValue : TValue;
begin
Result := EmptyStr;
losContext := TRttiContext.Create;
losContextType := losContext.GetType(TypeInfo(T));
if losContextType.TypeKind = tkRecord then
begin
for loclField in losContextType.GetFields do
begin
case loclField.FieldType.TypeKind of
tkRecord:
begin
losRecordRTTI := loclField.FieldType.AsRecord;
for loclRecordField in losRecordRTTI.GetFields do
begin
Result := Result + '|' + GetFieldValue<T>(Addr(piclObject), loclRecordField);
end;
end; // tkRecord
tkPointer:
begin
losPointerType := loclField.FieldType as TRttiPointerType;
// Check only record type pointers.
if losPointerType.ReferredType.TypeKind = tkRecord then
begin
losValue := loclField.GetValue(Addr(piclObject));
if (not losValue.IsEmpty) then
begin
for loclRecordField in losPointerType.ReferredType.GetFields do
begin
// Result := Result + '|' + ???????????
end;
end;
end;
end; // tkPointer
else
Result := Result + '|' + GetFieldValue<T>(Addr(piclObject), loclField);
end;
end;
end;
losContext.Free;
end;
在上面的示例中,当字段为tkPointer 指向记录类型时,我如何从中读取值?
【问题讨论】:
-
基本上我要做的是得到一个与记录中所有成员连接的字符串,即使它包含嵌套记录。
-
这不是 ParseAndReturnString 已经做的吗?递归调用它。
-
@DavidHeffernan 我需要从指针类型中获取值。请用???????????????查看评论
标签: delphi delphi-xe2 rtti delphi-xe3