Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Компоненты";
Текущий архив: 2006.06.18;
Скачать: [xml.tar.bz2];

Вниз

ПодСвойство компонента   Найти похожие ветки 

 
DimaBr   (2005-11-28 11:54) [0]

Здравствуйте !
Компонент имеет свойство типа

ThbStoredProc = class(TPersistent)
 private
   fStoredProcUpdate: TStoredProc;
   procedure SetStoredProcUpdate(const Value: TStoredProc);
 public
   constructor Create(AOwner: TComponent);
   destructor Destroy;override;
   procedure AssignTo(Source: TPersistent);override;
 published
   property StoredProcUpdate: TStoredProc read fStoredProcUpdate write SetStoredProcUpdate;
end;

...

constructor ThbStoredProc.Create(AOwner: TComponent);
begin
 fStoredProcUpdate := TStoredProc.Create(AOwner);
 fStoredProcUpdate.SetSubComponent(true);
 ...
end;

То есть свойство сомпонента состоит из StoredProc и других подсвойств. При выборе процедуры и присвоении параметров
в DFM-ке видим

StoredProc.StoredProcUpdate.DatabaseName = "SalaryODBC"
StoredProc.StoredProcUpdate.StoredProcName = "EmployeeUpdate;1"
StoredProc.StoredProcUpdate.ParamData = <
     item
       StoredProc.StoredProcUpdate.DataType = ftInteger
       StoredProc.StoredProcUpdate.Name = "@RETURN_VALUE"
       StoredProc.StoredProcUpdate.ParamType = ptResult
     end
     item
       StoredProc.StoredProcUpdate.DataType = ftString
       StoredProc.StoredProcUpdate.Name = "@NameLeftEmployee"
       StoredProc.StoredProcUpdate.ParamType = ptInput
     end>

Но при чтении из ресурса возникает ошибка:
"Error reading
TParam StoredProc.StoredProcUpdate.DataType: Property StoredProc does not exists."

Получается что подсвойство создаётся раньше свойства, что ли ? Как с этим бороться ?


 
Юрий Зотов ©   (2005-11-28 15:03) [1]

1. Как объявлено свойство в самом компоненте?
2. Нигде в конструкторе не пропущено inherited?


 
DimaBr   (2005-11-28 17:07) [2]


type
THandBook = class(TComponent)
 private
   fStoredProc: ThbStoredProc;
   procedure SetStoredProc(const Value: ThbStoredProc);
 public
   constructor Create(AOwner: TComponent);override;
   destructor Destroy; override;override;
 published
   property StoredProc: ThbStoredProc read fStoredProc write SetStoredProc;
 end;

...

constructor THandBook.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 fStoredProc := ThbStoredProc.Create(self);
...
end;

procedure THandBook.SetStoredProc(const Value: ThbStoredProc);
begin
 fStoredProc.AssignTo(Value);
end;

{ ThbStoredProc }
constructor ThbStoredProc.Create(AOwner: TComponent);
begin
 fHandBook := AOwner; //  << указаткль на родителя
 fStoredProcUpdate := TStoredProc.Create(fHandBook);
 fStoredProcUpdate.SetSubComponent(true);
end;
procedure ThbStoredProc.AssignTo(Source: TPersistent);
begin
 if Source is ThbStoredProc then begin
   self.fStoredProcUpdate := ThbStoredProc(Source).StoredProcUpdate;
 end{if}
end;


 
Юрий Зотов ©   (2005-11-28 18:55) [3]

fStoredProcUpdate создается с Owner=fHandBook и ему устанавливается SetSubComponent. Таким образом, он будет запоминаться внутри fHandBook, а не внутри ThbStoredProc - что мы и видим в DFM.

Видимо, Owner надо проставить в nil, а SetSubComponent убрать. Сохранять внутри ThbStoredProc, ручками (через DefineProperties и WriteComponent). И не забыть уничтожить в деструкторе ThbStoredProc.


 
DimaBr   (2005-11-29 08:35) [4]

То есть нужно, что бы запоминался не в родителе, а в классе TPersistent.
Для этого переопределяем WriteComponent в котором пишем

Procedure ThbStoredProc.WriteComponent(Writer: TWriter);
begin
 Writer.WriteComponent(fStoredProcUpdate);
end;

Я правильно мыслю ?


 
Юрий Зотов ©   (2005-11-29 08:49) [5]

Для этого перекрываем метод DefineProperties и пишем к нему ReadXXX и WriteXXX (вызывая внутри ReadComponent и WriteComponent). А чтобы не было двойного сохранения, к объявлению свойства дописываем stored False.


 
DimaBr   (2005-11-29 09:25) [6]

Спасибо, буду пробывать.


 
DimaBr   (2005-11-29 10:44) [7]

Ничего не получается.
При применении Вашего совета [3] в инспекторе пропадает вложенный компонент, остаётся как ссылка (то есть можно выбрать из уже имеющихся на форме). Помогите пожалуйста !
Вот урезал компонет до одного модуля и одного свойства.

unit HandBook;

interface

uses Classes, DBTables;

type
ThbStoredProc = class;
THandBook = class(TComponent)
 private
   fStoredProc: ThbStoredProc;
   procedure SetStoredProc(const Value: ThbStoredProc);
 public
   constructor Create(AOwner: TComponent);override;
   destructor Destroy; override;
 published
   property StoredProc: ThbStoredProc read fStoredProc write SetStoredProc;
 end;

ThbStoredProc = class(TPersistent)
 private
   fHandBook: TComponent;
   fStoredProcShow: TStoredProc;
   procedure SetStoredProcShow(const Value: TStoredProc);
   procedure WriteStoredProc(Writer: TWriter);
   procedure ReadStoredProc(Reader: TReader);
 public
   procedure DefineProperties(Filer: TFiler); override;
   constructor Create(AOwner: TComponent);
   destructor Destroy;override;
   procedure AssignTo(Source: TPersistent);override;
 published
   property StoredProcShow: TStoredProc read fStoredProcShow write SetStoredProcShow stored false;
end;

procedure Register;

implementation

{ THandBook }
constructor THandBook.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 fStoredProc := ThbStoredProc.Create(self);
end;

destructor THandBook.Destroy;
begin
 fStoredProc.Free;
 inherited;
end;

procedure THandBook.SetStoredProc(const Value: ThbStoredProc);
begin
 fStoredProc.AssignTo(Value);
end;

{ ThbStoredProc }
constructor ThbStoredProc.Create(AOwner: TComponent);
begin
 inherited Create;
 fHandBook := AOwner;
 fStoredProcShow := TStoredProc.Create(nil);
 //fStoredProcShow.SetSubComponent(true);
end;

destructor ThbStoredProc.Destroy;
begin
 fHandBook := nil;
 fStoredProcShow.Free;
 inherited;
end;

procedure ThbStoredProc.SetStoredProcShow(const Value: TStoredProc);
begin
 fStoredProcShow := Value;
end;

procedure ThbStoredProc.AssignTo(Source: TPersistent);
begin
 if Source is ThbStoredProc then begin
   self.fStoredProcShow := ThbStoredProc(Source).StoredProcShow;
 end{if}
end;

procedure ThbStoredProc.DefineProperties(Filer: TFiler);
begin
 inherited;
 Filer.DefineProperty("StoredProcShow", ReadStoredProc,WriteStoredProc,true);
end;

procedure ThbStoredProc.ReadStoredProc(Reader: TReader);
begin
 fStoredProcShow := TStoredProc(Reader.ReadComponent(nil));
end;

procedure ThbStoredProc.WriteStoredProc(Writer: TWriter);
begin
 Writer.WriteComponent(fStoredProcShow);
end;

procedure Register;
begin
 RegisterComponents("Standard", [THandBook]);
end;

end.


 
Макс Черных ©   (2005-12-01 21:32) [8]

public
  ...
  procedure AssignTo(Source: TPersistent);override;
  ...
end;


Что то тут явно перепутано. В модуле Classes объявлено:

protected
  procedure AssignTo(Dest: TPersistent); virtual;


Похоже перепутаны Assign и AssignTo, а это совсем не одно и то-же.


 
DimaBr   (2005-12-02 14:47) [9]

 TPersistent = class(TObject)
 private
   procedure AssignError(Source: TPersistent);
 protected
   procedure AssignTo(Dest: TPersistent); virtual;
   procedure DefineProperties(Filer: TFiler); virtual;
   function  GetOwner: TPersistent; dynamic;
 public
   destructor Destroy; override;
   procedure Assign(Source: TPersistent); virtual;
   function  GetNamePath: string; dynamic;
 end;


 
Макс Черных ©   (2005-12-02 17:01) [10]

2 DimaBr

Выдержка из Classes, занимательная, конечно.
Но все таки, каким образом AssignTo(Dest: TPersistent) у Вас превратился в AssignTo(Source: TPersistent) и самое главное - зачем?

Неудивительно, что при загрузке свойств все сходит с ума. Так как, там именно Assign и используется.


 
jack128 ©   (2005-12-02 21:30) [11]

Макс Черных ©   (01.12.05 21:32) [8]
а это совсем не одно и то-же.


Я бы сказал это прямо противоположные вещи ;)  Но наврядли это имеет отнашение  к делу.

DimaBr   (29.11.05 10:44) [7]
//fStoredProcShow.SetSubComponent(true);

раскомментируй эту строчку.


 
Макс Черных ©   (2005-12-03 17:29) [12]


> Но наврядли это имеет отнашение  к делу


Да ну?

Давайте посмотрим, у товарища DimaBr написано:

procedure THandBook.SetStoredProc(const Value: ThbStoredProc);
begin
fStoredProc.AssignTo(Value);
end;


При загрузке формы, fStoredProc изначально равен nil, и этому полю ничего не присваивается. Неудивительно, что "Получается что подсвойство создаётся раньше свойства".

Это ведь вообще азы. Надо писать Assign как положено, и все будет работать без всяких DefineProperties.


 
jack128 ©   (2005-12-03 18:23) [13]

Макс Черных ©   (03.12.05 17:29) [12]
fStoredProc изначально равен nil,

это не так, он создается в конструкторе THandBook. И все таки, хотя указаная тобой ошибка, без сомнения есть, но на механизм загрузки она повлиять не может.


 
Макс Черных ©   (2005-12-03 19:17) [14]


> fStoredProc изначально равен nil,
> это не так, он создается в конструкторе THandBook.


Ну тут я согласен, имелось в виду, что он не проинициализирован.
А вот насчет того, что не повлияет на загрузку - еще как повлияет

Посмотри, только внимательно:

StoredProc.StoredProcUpdate.DatabaseName = "SalaryODBC"
StoredProc.StoredProcUpdate.StoredProcName = "EmployeeUpdate;1"
StoredProc.StoredProcUpdate.ParamData = <
    item
      StoredProc.StoredProcUpdate.DataType = ftInteger
      StoredProc.StoredProcUpdate.Name = "@RETURN_VALUE"
      StoredProc.StoredProcUpdate.ParamType = ptResult
    end
    item
      StoredProc.StoredProcUpdate.DataType = ftString
      StoredProc.StoredProcUpdate.Name = "@NameLeftEmployee"
      StoredProc.StoredProcUpdate.ParamType = ptInput
    end>


И куда по твоему должно присваиваться то, что написано между item и end ?  

P.S. надо срочно кондиционер чинить, то скоро у меня все работники перегреются :)


 
jack128 ©   (2005-12-03 20:01) [15]

Макс Черных ©   (03.12.05 19:17) [14]
И куда по твоему должно присваиваться то, что написано между item и end ?  

Ну присваиваться то ему некуда, но это не из-за глюка в Assign(To).  Я же не просто так говорю, я сейчас тестовый пример накатал, пакет сделал. В конце концов можно просто убрать метод Assign , от этого ничего не измениться.

Тут нужно долго и упорно сидеть под дебагером и смотреть механизм стриминга дельфи. Мне этим лень заниматься, но кое какие соображения есть. Есть достаточно известный компонент VirtualTree, там у человека возникла похожая(ИМХО один в один) проблема.  
Итак есть компонент TbaseVirtualTree, у него есть свойство VTHeader - наследник TPersistent. У этого свойства есть подсвойство - коллекция Columns. Как видешь от сабжевого варинта отличает отсутствием промежуточного компонента TStoredProc.
И вот как Майк(автор компонента) изваращается и вот что он пишет по этому поводу(ключевые моменты я выделил):

type
 // --- HACK WARNING!
 // This type cast is a partial rewrite of the private section of TWriter. The purpose is to have access to
 // the FPropPath member, which is otherwise not accessible. The reason why this access is needed is that
 // with nested components this member contains unneeded property path information(то что мы видем). These information prevent
 // successful load of the stored properties later.
 // In Classes.pas you can see that FPropPath is reset several times to "" to prevent this case for certain properies.
 // Unfortunately, there is no clean way for us here to do the same.
 {$hints off}
 TWriterHack = class(TFiler)
 private
   FRootAncestor: TComponent;
   FPropPath: string;
 end;
 {$hints on}

procedure TVTHeader.WriteColumns(Writer: TWriter);

// Write out the columns but take care for the case VT is a nested component.

var
 LastPropPath: String;
 
begin
 // Save last property path for restoration.
 LastPropPath := TWriterHack(Writer).FPropPath;
 try
   // If VT is a nested component then (вспоминаем, что StoredProp у нас как nested component) this path contains the name of the parent component at this time
   // (otherwise it is already empty). This path is then combined with the property name under which the tree
   // is defined in the parent component. Unfortunately, the load code in Classes.pas does not consider this case
   // is then unable to load this property.
   TWriterHack(Writer).FPropPath := "";
   Writer.WriteCollection(Columns);
 finally
   TWriterHack(Writer).FPropPath := LastPropPath;
 end;
end;

Макс Черных ©   (03.12.05 19:17) [14]
надо срочно кондиционер чинить, то скоро у меня все работники перегреются :)

я не против ;)


 
jack128 ©   (2005-12-03 20:22) [16]

Да. Но это все теория. С практической точки зрения я бы просто отказался от класса ThbStoredProc, а сделал бы наследника TStoredProc и перенёс бы весь функционал в него.


 
Макс Черных ©   (2005-12-03 21:33) [17]

2 jack128.

Ладно, насчет чудес со стримингом в Delphi убедил.
Проблема описана и в Quality Central, рекомендую почитать:
http://qc.borland.com/wc/qcmain.aspx?d=11126

Тем не менее, Assign все равно надо писать правильно.


> надо срочно кондиционер чинить, то скоро у меня все работники
> перегреются :)
> я не против ;)


Говорят, что он (кондер) совсем мертвый, чинить невыгодно. Менять будем на кокой нибудь путевый.



Страницы: 1 вся ветка

Форум: "Компоненты";
Текущий архив: 2006.06.18;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.013 c
6-1135885674
ZeFiR
2005-12-29 22:47
2006.06.18
WAP-браузер


15-1148225596
antonn
2006-05-21 19:33
2006.06.18
Профессии...


2-1148683470
yaro
2006-05-27 02:44
2006.06.18
Даже не знаю как написать


15-1148649062
DSKalugin
2006-05-26 17:11
2006.06.18
Переход с Delphi7 на 2006. Стоит ли?


3-1145957654
kyn66
2006-04-25 13:34
2006.06.18
SQL-запрос с параметрами выдает ошибки





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский