Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.48 MB
Время: 0.026 c
4-84814
1g0r
2003-04-22 13:53
2003.06.26
глубина цвета в HBITMAP, созданной CreateCompatibleBitmap()


3-83921
Крот
2003-05-29 12:44
2003.06.26
Операция побитового AND в SQL


1-84084
kah68
2003-06-10 12:39
2003.06.26
Не обязательный параметр


4-84850
Airdriver
2003-04-26 12:34
2003.06.26
---|Ветка была без названия|---


14-84522
Silver_
2003-06-06 15:25
2003.06.26
где посмотреть значение констант dsEdit, dsInsert, ...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский