我在尝试使用 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
指向记录类型时,我如何从中读取值?