我通过在我的 TPersistent 后代中实现 DefineProperties 方法解决了这个问题。我想为这个问题制定一个通用的解决方案,我可以轻松地在我的所有对象中为所有相关属性实现它。下面是它的外观:
TOverridePropFiler = class
private
FReadWritePropName: string;
FObject: TObject;
procedure ReadOverrideProp(Reader: TReader);
procedure WriteOverrideProp(Writer: TWriter);
public
constructor Create(Filer:TFiler; Obj:TObject; Name:string);
end;
{ TOverridePropFiler }
constructor TOverridePropFiler.Create(Filer:TFiler; Obj:TObject; Name:string);
begin
FReadWritePropName:=Name;
FObject:=obj;
if (Name='') or not Assigned(GetPropInfo(Obj,Name)) then
Raise Exception.CreateFmt('Property %s not found in object %s',[Name,Obj.ClassName]);
Filer.DefineProperty(Name, ReadOverrideProp, WriteOverrideProp,
GetPropValue(FObject,FReadWritePropName,False)<>uiFloat);
end;
procedure TOverridePropFiler.ReadOverrideProp(Reader: TReader);
begin
SetPropValue(FObject,FReadWritePropName,Reader.ReadFloat);
end;
procedure TOverridePropFiler.WriteOverrideProp(Writer: TWriter);
begin
Writer.WriteDouble(GetPropValue(FObject,FReadWritePropName,False));
end;
我在我的 DefineProperties 方法中调用它如下:
procedure TMyObj.DefineProperties(Filer: TFiler);
begin
inherited;
TOverridePropFiler.Create(Filer,Self,'dTOverride').Free;
end;
为了使这个通用化,我必须使用 RTTI 并在本地保存属性名称(不可能从 TWriter 中得到它,并且需要对 TReader 进行 hack)。为了使其线程安全(并且因为 TFiler.DefineProperty 需要“对象”函数),我将整个东西封装在一个对象中。
就我而言,我希望默认值为 uiFloat。这个常数可以设置为任何你想要的。如果您想为不同的属性设置不同的默认值,您可以轻松地将默认值作为参数添加到 Create 函数中。
请注意,您仍然需要在 TMyObj 的构造函数中将属性设置为默认值。
在我看来,这是解决 Delphi 中一个相当严重的限制的一种相当有效的方法。
编辑:您需要记住将“stored false”添加到所有使用它的属性。