这是一个简单的测试,演示了我在使用 Delphi 2007 的项目中遇到的问题。我使用 TComponent 类来存储组件的各种状态。但 Int64 属性编写器方法永远不会被调用(仅设置目标字段)。所以不可能依赖作者来更新 GUI、TList 或类似的东西......
例如:
TTestClass = Class(TComponent)
Private
Fb: Int64;
Fa: Integer;
Procedure SetFa(Const Value: Integer);
Procedure SetFb(Const Value: Int64);
Published
Property a: Integer Read Fa Write SetFa;
Property b: Int64 Read Fb Write SetFb;
Public
Procedure SaveInstance(Var Str: TStream);
Procedure LoadInstance(Var Str: TStream);
Procedure ReallyLoadInstance(Var Str: TStream);
Procedure Assign(Source: TPersistent); Override;
End;
TForm1 = Class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Procedure Button1Click(Sender: TObject); // test: 1st step, save the class
Procedure Button2Click(Sender: TObject); // test: 2nd step, try and fail to reload
Procedure Button3Click(Sender: TObject); // test: 3rd step, successfull reloading
Private
TestClass: TTestClass;
Str: TStream;
Public
Constructor Create(AOwner: TComponent); Override;
Destructor Destroy; Override;
End;
Var
Form1: TForm1;
Implementation
{$R *.dfm}
Procedure TTestClass.SetFa(Const Value: Integer);
Begin
Fa := Value;
ShowMessage('ok for "simple types"....');
End;
Procedure TTestClass.SetFb(Const Value: Int64);
Begin
Fb := Value;
ShowMessage('and for the others');
End;
Procedure TTestClass.SaveInstance(Var Str: TStream);
Begin
Str.Position := 0;
Str.WriteComponent( Self );
End;
Procedure TTestClass.Assign(Source: TPersistent);
Begin
If Not (Source Is TTestClass) Then Inherited
Else
Begin
b := TTestClass(Source).Fb;
End;
End;
Procedure TTestClass.LoadInstance(Var Str: TStream);
Begin
Str.Position := 0;
// this will work for fa and not fb.
Str.ReadComponent(Self);
End;
Procedure TTestClass.ReallyLoadInstance(Var Str: TStream);
Begin
Str.Position := 0;
Assign( Str.ReadComponent(Nil));
End;
Constructor TForm1.Create(AOwner: TComponent);
Begin
RegisterClasses([TTestClass]);
Inherited;
TestClass := TTestClass.Create(Self);
Str := TmemoryStream.Create;
End;
Destructor TForm1.Destroy;
Begin
Str.Free;
Inherited;
End;
Procedure TForm1.Button1Click(Sender: TObject);
Begin
Str.Size := 0;
TestClass.SaveInstance(Str);
End;
Procedure TForm1.Button2Click(Sender: TObject);
Begin
If Str.Size = 0 Then Exit;
TestClass.LoadInstance(Str);
// guess what...only first message
End;
Procedure TForm1.Button3Click(Sender: TObject);
Begin
If Str.Size = 0 Then Exit;
TestClass.ReallyLoadInstance(Str);
End;
正如 TypInfo.pas 中那样,有一个“tkInt64”情况(似乎调用“SetProc”过程),不应该使用“Writer”设置已发布的 Int64-props(就像通常与其他“常见”操作一样) “类型)?
最佳答案
那是因为您从未给属性 b
赋值。因此它具有默认值(零)并且流系统不会将其保存到流中。由于它不在流中,因此在读回它时您不会看到调用的 setter...
实际上,由于您也没有为属性 a
赋值,因此它也会发生同样的事情。看起来像是流系统中的一个错误(或者至少是不一致):
- 也不应该将零值的
Integer
属性保存/加载到流中, - 或者它应该保存/加载它们,因为属性定义中没有
default
说明符,因此应该假设nodefault
,因此值始终被流式传输.
所以,回顾一下:在调用 TestClass.SaveInstance(Str);
之前添加 TestClass.b := 1;
并且您应该看到加载对象时调用的 setter从流返回,但当属性具有该类型的默认值时,您无法中继流系统来调用 setter。
关于delphi - 为什么不会调用已发布的 Int64 属性编写器方法 - 组件流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7306604/