2011-09-05 78 views
1

這是一個簡單的測試,演示了我在項目中遇到的問題,使用Delphi 2007.我使用TComponent類來存儲組件的各種狀態。但是從不調用Int64屬性編寫器方法(只設置目標字段)。因此,它不可能依靠作家更新的GUI的從TList或這樣的事情......爲什麼發佈的Int64屬性編寫器方法不會被調用 - 組件流

例如:

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」過程),不應該發佈-int64-props使用「Writer」來設置(通常與其他「常用」類型一樣)?

回答

7

這是因爲你永遠不會爲屬性b賦值。因此它具有默認值(零),並且流式傳輸系統不會將其保存到流中。而且,由於它不是流中,你不會看到閱讀它的時候回叫二傳手...

實際上,因爲你不分配值屬性a要麼,同樣的事情應與它發生。看起來像一個錯誤(或至少不一致)在流式傳輸系統:

  • 或者它不應該保存/零值到流過加載Integer屬性,
  • 或應保存/加載兩個因爲在屬性定義中沒有default說明符,因此nodefault應該被假定,因此該值總是被流式傳輸。

因此,要回顧:調用TestClass.SaveInstance(Str);前加TestClass.b := 1;,你應該看到從流加載對象回來時叫二傳手,但你不能流系統傳遞給調用設置方法時酒店默認類型的值。

+0

你說得對,我」我完全忘記了默認值沒有寫入。但是,這仍然會顯示一個錯誤,正如您在第一個列表中所說的那樣。 – az01

1

這似乎是Int64作爲一個屬性的錯誤。

作爲一種變通方法,你既可以使用另一種數據類型,如Integer,或者,如果不夠大,使用的DefineProperties和TFiler.DefineProperty,TFiler.DefineBinaryProperty等

相關問題