Rtti data manipulation and consistency in Delphi 2010

这一生的挚爱 提交于 2019-12-06 03:33:22

A TValue is designed to hold any kind of data in a very compact form, it's not designed to emulate an "pointer". Take a look in the RTTI.pas unit: TValue is a RECORD that only has one data member of the type TValueData. TValueData itself is itself a variant record.

Looking at TValueData you will see how it does NOT hold anything but the minimum amount of data: There's no way to know where that TValue came from.

The solution: Don't hold a TValue in your structures, replace it with a pair of TRttiField + an TObject. When you need the TValue use TRttiField.GetValue(Instance), when you want to set a value use TRttiField.SetValue(Instance, AValue:TValue).

Thanks Cosmin for your help, the solution is not to save a TValue in the structure but use a Pointer to the data and use the GetValue, SetValue methods of a field or property.

So here is how I solved it in my generic class:

TDataModel <T> = class
  private
    FType     : PTypeInfo;
    FInstance : Pointer;
  public 
    constructor Create (var Data : T);
    procedure ShowContent;
  end;

constructor TDataModel <T>.Create (var Data : T);

begin
FType := TypeInfo(T);
if FType.Kind = tkClass then
  FInstance := TObject (Data)
else if FType.Kind = tkRecord then
  FInstance := @Data;
end;

procedure TDataModel <T>.ShowContent;
var 
  Ctx   : TRttiContext;
  Field : TRttiField;

begin
for Field in Ctx.GetType (FType).GetFields do
  Writeln (Field.GetValue (FInstance).ToString);
end;

Now you can either change fields using the DataModel through or using the original record class.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!