为什么不调用已发布的Int64属性 - 编写器方法 - 组件流

az0*_*z01 1 delphi streaming components delphi-2007

这是一个简单的测试,演示了我在项目中遇到的问题,使用Delphi 2007.我使用TComponent类来存储组件的各种状态.但永远不会调用Int64属性writer方法(仅设置目标字段).因此,不可能依靠编写器来更新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;
Run Code Online (Sandbox Code Playgroud)

作为TypInfo.pas有一个"tkInt64"的情况下(这似乎称之为"SetProc"过程),不应该公布,Int64的道具使用的"作家"设置(如通常与其他"普通"类型的完成) ?

ain*_*ain 7

那是因为你从未为财产分配价值b.因此它具有默认值(零),并且流系统不会将其保存到流中.而且因为它不在流中,所以在阅读它时你不会看到调用的setter ...

实际上,既然你没有为属性赋值a,那么同样的事情也应该发生.看起来像流媒体系统中的错误(或至少是不一致):

  • 要么它不应该保存/加载Integer属性值为零的属性,
  • 或者它应该保存/加载它们,因为default属性定义中没有说明符,因此nodefault应该假定,因此值总是要流式传输.

因此,回顾一下:TestClass.b := 1;在调用之前添加TestClass.SaveInstance(Str);并且您应该看到在从流中加载对象时调用的setter,但是当属性具有类型的默认值时,您无法在流系统上中继以调用setter.