Rtti для Variant Records - PullRequest
3 голосов
/ 03 мая 2010

Я пытаюсь написать своего рода сериализатор объекта / записи с Delphi 2010 и задаюсь вопросом, есть ли способ определить, является ли запись вариантом записи. Например. запись TRect, как определено в Types.pas:

TRect = record
case Integer of
  0: (Left, Top, Right, Bottom: Longint);
  1: (TopLeft, BottomRight: TPoint);
end; 

Поскольку мой сериализатор должен рекурсивно работать с моими структурами данных, он будет спускаться в записи TPoint и генерировать избыточную информацию в моем сериализованном файле. Есть ли способ избежать этого, получив подробную информацию о записи?

1 Ответ

1 голос
/ 04 мая 2010

Одно решение может быть следующим:

procedure SerializeRecord (RttiRecord : TRttiRecord)

var
  AField : TRttiField;
  Offset : Integer;

begin
Offset := 0;
for AField in RttiRecord.Fields do
  begin
  if AField.Offset < Offset then Exit;
  Offset := AField.Offset; //store last offset
  SerializeField (AField);
  end;
end;

Но это решение не является правильным решением для всех случаев. Он работает только для сериализации, если разные варианты содержат одинаковую информацию и одинаковые типы. Если у вас есть что-то вроде следующего (с wikipedia.org):

type   
  TVarRec = packed record
  case Byte of
    0: (FByte: Byte;
        FDouble: Double);
    1: (FStr: ShortString);
  end;

Вы бы сериализовали

FByte=6
FDouble=1.81630607010916E-0310

или лучше сериализовать

FStr=Hello!

Да, конечно, это также относится и к компьютеру, но не к файлу, который должен быть читаемым или даже редактируемым для человека.

Так что я думаю, что единственный способ решить проблему - это использовать Атрибут, чтобы определить, какой вариант следует использовать для сериализации.

...