delphi的持久化能力是相对比较弱的,但是所谓的弱只是说我们需要多做点事,要不delphi的ide如何持久化那些控件呢,由于这些控件大都继承自tpersitent,所以很多人都认为:delphi持久化的对象必须是继承自tpersitent!真的如此吗?这种理解是错误的,正确的理解:只要正确利用delphi持久化机制,就可以实现持久化,只不过需要借助tpersitent或tconponent类来进行而已!
那么要怎么借助呢?李维的《深入vcl》书里首先明确告诉你一个很残酷的事实:即使自定义的类继承自tcomponent,而对其中需要保存的变量不做如何持久机制处理,那么调用stream的wtitecomponent方法来保存这个自定义类,是无法保持这个类里的这些数据的——打开文件的结果可以看到那些需要保存的变量都没存到文件里;其实,dfm里保存的也只是控件的部分属性,这是因为要想保存数据必须做2件事:
1.重写defineproperties方法;
2.对要保存的变量做持久机制处理;
vcl库对控件的部分需要保存属性(如:left、top)进行了封装,所以我们就不用干活了;而对于自定义的类,那就没办法了,老老实实按上述2个要求做吧!通常大家都知道如何持久普通数据类型,而遇到list,array这些组合型的数据就不了了之,网上的查询结果也很少提到这方面的问题!下面提供一个方法,供参考:
对于组合型数据,使用delphi的variant变量,variant的类型根据需要选取,这里假设要保存的是整型数组。示例代码:
TABC=class(TComponent)
private
c :Variant;
protected
procedure SetC(Value: Variant);
function getC():Variant;
procedure StoreArrayProperty(W:TWriter);
procedure ReadArrayProperty(R:TReader);
public
property c :Variant read getc write Setc;
procedure DefineProperties(F:TFiler); override;
......
end;
procedure TABC.ReadArrayProperty(R: TReader);
var
iLop :integer;
begin
if r.ReadBoolean then
begin
fc := vararraycreate([0, 10], varInteger);//创建数组空间
for iLop :=0 to 10 do
fc[iLop] :=r.ReadInteger;
end;
end;
procedure TABC.StoreArrayProperty(W: TWriter);
var
i:integer;
begin
w.WriteBoolean(True);
if fc<>Null then
begin
for i:=0 to 10 do
w.writeinteger(fc[i]);
end;
end;
procedure TABC.DefineProperties(F: TFiler);
begin
inherited;
F.DefineProperty('ArrayPro', ReadArrayProperty, StoreArrayProperty, True);
end;
测试代码:
procedure TForm1.btn1Click(Sender: TObject);
var
i,j :integer;
abc :TABC;
MS :TMemoryStream;
a :variant;
begin
MS :=TMemoryStream.Create;
for i:=0 to 10 do
begin
abc :=TABC.Create(nil);
a := vararraycreate([0, 10], varInteger);
For j:=0 to 10 do
a[j] :=j;
abc.c :=a;
MS.WriteComponent(abc);
end;
MS.SaveToFile('C:\test.dat');
FreeAndNil(MS);
end;
procedure TForm1.btn2Click(Sender: TObject);
var
MS :TMemoryStream;
i ,j:integer;
abc :TABC;
s:string;
begin
mmo1.Lines.Clear;
try
Classes.FindClass('Tabc');
except
Classes.RegisterClass(TABC);
end;
MS :=TMemoryStream.Create;
MS.LoadFromFile('c:\test.dat');
//MS.Position :=0;
for i:=0 to 10 do
begin
s :='';
abc :=TABC(MS.ReadComponent(nil));
if (abc <>nil) then
s :=s + IntToStr(abc.c[0]);
mmo1.Lines.Add( s);
end;
FreeAndNil(MS);
end;
对于持久化数据方法不甚了解的可以参考《深入vcl》,里面有详细说明!