Форум: "Основная";
Текущий архив: 2003.06.26;
Скачать: [xml.tar.bz2];
ВнизЧтение компонента Найти похожие ветки
← →
REA (2003-06-10 15:16) [0]Не могу разобраться в механизме чтения компонентов.
Если свойством компонента является объект (допустим наследник TPersistent), то каким образом ему присваивается значение при чтении (из ресурса, файла и т.п.)?
Объект создается, передается в процедуру установки свойства (SetSomething), потом я должен вызвать Assign и затем исходный объект удаляется. Так что ли? Не могу найти этому подтверждения.
А проблема следующая: если объект содержит много данных (допустим мегабайты), то вызов этого Assign это дополнительная трата времени и ресурсов.
← →
REA (2003-06-10 16:23) [1]Пока что обнаружил, что Tcollection и другие объекты грузятся по-разному. По-видимому для TCollection не нужно делать ничего (объект не уничтожается при загрузке, а его Items очищаются и создаются по Add), а для остальных объектов придется применять замороченную технику, описанную в Help.
Неужели никто не может просветить на этот счет?
← →
Lu Chan (2003-06-10 17:43) [2]Дело в том, что Assign для разных классов реализован по разному(сам понимаешь ;-)). Чего конкретно нужно сделать, может подсоблю.
>>The assignment operator makes Destination reference the same object as Source, whereas the Assign method copies the contents of the object referenced by Source into the object referenced by Destination.<- А, Это по поводу первого замечания, или я не совсем понял вопрос;-)?
← →
MalkoLinge (2003-06-10 18:39) [3]Assign реализован для всех одинаково, перекрывают AssignTo.
Иногда действительно нужно избегать использования Assign... Хотя это неприятная процедура ( например вызвать метод фрее итемсов листбокса, а потом этому же свойству передать указатель на Ваш стринг лист ). Только перед тем как эксперементировать очень бы рекомендовал посмотреть код компоненты, которую Вы планируете мучать :)))
← →
Lu Chan (2003-06-10 18:46) [4]Был не прав.
← →
icWasya (2003-06-10 18:54) [5]вот за пять минут
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
// Собственно компонента
type
TMyClass2=class;
TMyClass1=class(TPersistent)
private
FS1:String;
FS2:Integer;
FM2: TMyClass2;
procedure SetS1(const Value: String);
procedure SetS2(const Value: Integer);
public
function GetOwner: TPersistent; override;
procedure Assign(Source:TPersistent);override;
published
property S1:String read FS1 write SetS1;
property S2:Integer read FS2 write SetS2;
end;
TMyClass2=class(TComponent)
private
FN1: String;
FM1: TMyClass1;
procedure SetM1(const Value: TMyClass1);
procedure SetN1(const Value: String);
public
constructor Create(AOwner:TComponent);Override;
published
property N1:String read FN1 write SetN1;
property M1:TMyClass1 read FM1 write SetM1;
end;
{ TMyClass1 }
procedure TMyClass1.Assign(Source: TPersistent);
begin
if Source is TMyClass1 then begin
FS1:=TMyClass1(Source).FS1;
FS2:=TMyClass1(Source).FS2;
end else
inherited;
end;
function TMyClass1.GetOwner: TPersistent;
begin
Result:=FM2;
end;
procedure TMyClass1.SetS1(const Value: String);
begin
FS1 := Value;
end;
procedure TMyClass1.SetS2(const Value: Integer);
begin
FS2 := Value;
end;
{ TMyClass2 }
constructor TMyClass2.Create(AOwner:TComponent);
begin
inherited;
FM1:=TMyClass1.Create;
FM1 .FM2:=Self;
end;
procedure TMyClass2.SetM1(const Value: TMyClass1);
begin
FM1 .Assign(Value);
end;
procedure TMyClass2.SetN1(const Value: String);
begin
FN1 := Value;
end;
// теперь запись
procedure TForm1.Button1Click(Sender: TObject);
var M2:TMyClass2;
Dat,Txt:TStream;
begin
// создаём компоненту
M2:=TMyClass2.Create(Nil);
// присваиваем свойства
M2.N1:="Тест";
M2.M1.S1:="Текст";
M2.M1.S2:=1024;
создаём
Dat:=TFileStream.Create("Stream.DAT",fmCreate);
try
// собственно пишем компоненту в поток
Dat.WriteComponent(M2);
// на всякий случай перепишем в виде текста
// что бы посмотреть, что получилось
Txt:=TFileStream.Create("Stream.txt",fmCreate);
try
Dat.Seek(0,0);
ObjectBinaryToText(Dat, Txt);
finally
Txt.Free;
end;
finally
Dat.Free;
end;
M2.Free;
end;
// а теперь прочитаем
procedure TForm1.Button2Click(Sender: TObject);
var M2:TMyClass2;
Dat:TStream;
begin
M2:=TMyClass2.Create(Nil);
Dat:=TFileStream.Create("Stream.DAT",fmOpenRead);
try
Dat.ReadComponent(M2);
finally
Dat.Free;
end;
// и посмотрим что получилось
Memo1.Lines.Add("M2.N1 = "+M2.N1);
Memo1.Lines.Add("M2.M1.S1 = "+M2.M1.S1);
Memo1.Lines.Add("M2.M2.S2 = "+IntToStr(M2.M1.S2));
M2.Free;
end;
end.
← →
REA (2003-06-10 19:20) [6]Вот в этом месте:
procedure TMyClass2.SetM1(const Value: TMyClass1);
begin
FM1 .Assign(Value);
end;
FM1 не является наследником TCollection, поэтому я подозреваю, что при чтении ресурса класса вызовется SetM1, в которой вызывается Assign. При этом Value после выхода должен кто-то убить (чего я не нашел в TReader). Вопрос является ли правомерным использование Assign при чтении (и присвоении свойства) для наследников TPersistent? В Help не нашел.
Кроме того у меня Value может быть большим (теоретически до гигабайта) и тогда FM1.Free; FM1 := Value сэкономит ресурсы, если Value никто не убивает (а вроде никто и не должен при чтении).
← →
reonid (2003-06-10 19:36) [7]>Если свойством компонента является объект (допустим наследник >TPersistent), то каким образом ему присваивается значение при >чтении (из ресурса, файла и т.п.)?
>Объект создается, передается в процедуру установки свойства
> (SetSomething), потом я должен вызвать Assign и затем исходный > объект удаляется. Так что ли?
Ничего подобного. Set-методы для объектов не вызываются.
Вместо этого они сами читают все свои св-ва из потока.
Никаких лишних созданий-разрушений не происходит.
← →
REA (2003-06-10 19:46) [8]Угу. Дошло уже - для сохранения и чтения достаточно Get. Проверил вот. Всем спасибо!
← →
icWasya (2003-06-11 10:20) [9]Если проверить, какие процедуры вызываются при ReadComponent в приведённом коде, то увидите, что Assign нигде не вызывается.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.06.26;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.026 c