-
Где ошибка?
unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end;
My=class(TComponent) public s:string; end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); var f:TFileStream; x:My; begin f:=TFileStream.Create('d:\Test',fmCreate or fmopenwrite); x:=My.Create(nil); x.s:='Test'; f.WriteComponent(x); f.Free; x.Free; end;
procedure TForm1.Button2Click(Sender: TObject); var f:TFileStream; x:My; begin f:=TFileStream.Create('d:\Test',fmOpenRead); x:=f.ReadComponent(nil) as My; ShowMessage(x.s); f.Free; x.Free; end;
begin RegisterClass(My); end.
-
> Где ошибка?
S должно быть свойством. S должно быть объявлено в секции published. Ну и должно, ес-но, иметь сеттер.
-
Точнее, не сам сеттер, а атрибут write.
-
Спасибо буду пробовать :)
-
> S должно быть объявлено в секции published.
Не подходит, мне надо свойства-массивы сохранять, а их нельзя объявить published :(
Есть другой способ сохранение экземпляров?
-
> Святослав (29.10.07 17:23) [4]
> а их нельзя объявить published
Можно, в виде индексированного свойства (cм., например, объявление свойства Items у класса TStrings). Кроме того, с помощью DefineProperties можно сохранять свойства любого типа.
-
> Можно, в виде индексированного свойства
если так: published property Word[i:integer]:string read GetS Write SetS; то выдает - Published property 'Word' cannot be of type ARRAY (E2188)
> cм., например, объявление свойства Items у класса TStrings
в Delphi 2006 у класса TStrings нет свойства Items, TList подойдет?
-
Оставляя за пределом обсуждений факт целесообразности динамического массива в качестве свойства, а также некоторые нюансы реализации, общая схема может быть такова: unit Unit2;
interface
uses SysUtils, Classes;
type
TWords = array of string;
TMyStoreClass = class (TComponent)
private
FWords: TWords;
procedure SetWords(const Value: TWords);
procedure ReadWords (Reader: TReader);
procedure WriteWords (Writer: TWriter);
protected
procedure DefineProperties(Filer: TFiler); override;
public
property Words: TWords read FWords write SetWords;
procedure AddWord (const S: string);
end;
implementation
procedure TMyStoreClass.AddWord(const S: string);
begin
SetLength (FWords,Length(FWords)+1);
FWords[Length(FWords)] := S
end;
procedure TMyStoreClass.DefineProperties(Filer: TFiler);
begin
inherited;
Filer.DefineProperty('Words',ReadWords,WriteWords,True);
end;
procedure TMyStoreClass.ReadWords(Reader: TReader);
var
I,
WordCount,
WordLength: Integer;
S: string;
begin
Reader.Read(WordCount,SizeOf(WordCount));
SetLength (FWords,WordCount);
for I := 0 to WordCount-1 do
begin
Reader.Read(WordLength,SizeOf(WordLength));
SetLength (S,WordLength);
Reader.Read(S[1],WordLength);
FWords[I] := S
end;
end;
procedure TMyStoreClass.SetWords(const Value: TWords);
begin
FWords := Value;
end;
procedure TMyStoreClass.WriteWords(Writer: TWriter);
var
I,
WordCount,
WordLength: Integer;
S: string;
begin
WordCount := Length(FWords);
Writer.Write(WordCount,SizeOf(WordCount));
for I := 0 to WordCount-1 do
begin
S := Words[I];
WordLength := Length(S);
Writer.Write(WordLength,SizeOf(WordLength));
Writer.Write(S[1],WordLength);
end;
end;
end.
-
Т.е., это пример использования DefineProperties для сохранения/чтения *любого* свойства, а не панацея для данного случая, конечно.
-
проблема: при попытке обращения FWords через Words или AddWord, программа вылетает! Если б это был класс его надо было бы создать, но так как это массив достаточно задать размерность что и происходит в AddWord… В чем ошибка?
-
Да я просто показал, как работать с DefineProperty, остальное -- довесок, написанный с закрытыми глазами за минуту, на него не нужно обращать внимание. А если начать обращать, то видно что в AddWord содержится ошибка, а именно: FWords[Length(FWords)-1] := S
:)
-
Вот, если угодно, код проверки: procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
Store: TMyStoreClass;
Fs: TFileStream;
begin
Store := TMyStoreClass.Create(nil);
try
Store.AddWord('First');
Store.AddWord('Second');
Fs := TFileStream.Create('d:\store.dat',fmCreate);
try
Fs.WriteComponent(Store);
finally
Fs.Free
end;
finally
Store.Free;
end;
Store := TMyStoreClass.Create(nil);
try
Fs := TFileStream.Create('d:\store.dat',fmOpenRead);
try
Fs.ReadComponent(Store);
finally
Fs.Free
end;
for I := Low(Store.Words) to High(Store.Words) do
begin
ShowMessage (Store.Words[I]);
end;
finally
Store.Free;
end;
end;
-
Действительно ошибка :) Если я правильно понял то ReadComponent подставляет сохраненные значения в свойство Words (в обход AddWord) или там другой механизм?
-
> [12] Святослав (30.10.07 01:05) > Действительно ошибка :) > Если я правильно понял то ReadComponent подставляет сохраненные > значения в свойство Words (в обход AddWord) или там другой > механизм?
Там другой механизм. Вся механика — в классах TComponent и TPersistent. Изучайте, там на самом деле много «вкусных» и поучительных вещей. :)
-
Огромное всем и Джо отдельное человечиское спасибо :))) Заключение: Много работать вредно! Я забыл проинициализировать свой объект, поэтому прога вылетала, а из-за усталости немог увидеть :) Если глюк неиспровляеться в течении полу часа лутше лечь поспать и все проидет :)
|