Rtti数据处理和Delphi 2010中的一致性

时间:2010-05-05 09:17:27

标签: delphi delphi-2010 rtti tvalue

有没有人知道,如何使用对原始数据的引用来制作TValue?在我的序列化项目中,我使用(如XML-Serialization中所建议的)通用序列化程序,它将TValues存储在内部树结构中(类似于示例中的MemberMap)。

此成员树还应用于创建动态设置表单并操纵数据。 我的想法是为数据定义一个属性:

TDataModel <T> = class
  {...}
  private
    FData : TValue;
    function GetData : T;
    procedure SetData (Value : T);
  public
    property Data : T read GetData write SetData;
end;

GetData,SetData方法的实现:

procedure TDataModel <T>.SetData (Value : T);

begin
FData := TValue.From <T> (Value);
end;

procedure TDataModel <T>.GetData : T;

begin
Result := FData.AsType <T>;
end;

不幸的是,TValue.From方法总是复制原始数据。因此,只要应用程序对数据进行更改,DataModel就不会更新,反之亦然,如果我以动态形式更改DataModel,原始数据不会受到影响。 当然,我总是可以在更改任何内容之前和之后使用Data属性,但是由于我在DataModel中使用了很多Rtti,所以我不想随时都这样做。

也许某人有更好的建议?

2 个答案:

答案 0 :(得分:4)

TValue旨在以非常紧凑的形式保存任何类型的数据,它不是为了模拟“指针”而设计的。看一下RTTI.pas单元:TValue是一个只有一个TValueData类型的数据成员的RECORD。 TValueData本身就是一个变种记录。

看看TValueData,你会看到它除了最少量的数据之外什么都没有:没有办法知道TValue来自哪里。

解决方案:不要在结构中放置TValue,用一对TRttiField + TObject替换它。当你需要TValue时使用TRttiField.GetValue(Instance),当你想设置一个值时,使用TRttiField.SetValue(Instance,AValue:TValue)。

答案 1 :(得分:0)

感谢Cosmin的帮助,解决方法不是在结构中保存TValue,而是使用指向数据的指针并使用字段或属性的GetValue,SetValue方法。

所以这就是我在泛型类中解决它的方法:

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;

现在,您可以使用DataModel或使用原始记录类更改字段。