Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Notification не вызывается.


Автор: Beltar 27.12.2006, 21:08
Делаю компонент, содержащий формочку для показа справочников баз данных, чтобы не делать одно и то же в разных проектах. Таблицы содержаться в коллекции, точнее включены в элемент коллекции типа TListTable (всего 4 класса):

Код

  TListTable=class(TCollectionItem)
  private
    FTable:TADOTable;
    procedure SetTable(Value:TADOTable);
  published
    property Table:TADOTable read FTable write SetTable;
  end;

  TTables=class(TCollection)
  private
    FOwner:TAvgClassifierForm;
    function GetItem(Index: Integer): TListTable;
    procedure SetItem(Index: Integer; const Value: TListTable);
    function Add:TListTable;
    procedure Delete(Index:Integer);
    function Insert(Index:Integer):TListTable;
  protected
    function GetOwner: TComponent;
  public
    property Items[Index: Integer]: TListTable read GetItem write SetItem; default;
    constructor Create(AOwner:TAvgClassifierForm);
  published
  end;


У TListTable

Код

procedure TListTable.SetTable(Value: TADOTable);
var NC:TAvgClassifierForm;
begin
if FTable<>Value then
  begin
  FTable:=Value;
  NC:=TAvgClassifierForm((Self.Collection as TTables).GetOwner);
  Value.FreeNotification(NC);
  end;
end;


Т. е. получаю владельца коллекции (сам компонент) и прошу таблицу уведомлять его о своей смерти.

Сам Notification:

Код

procedure TAvgClassifierForm.Notification(AComponent: TComponent;
  Operation: TOperation);
var i:Integer;
begin
inherited Notification(AComponent,Operation);
if (Operation=opRemove) then
  begin
  for i := 0 to FTables.Count - 1 do
    if FTables[i].FTable=AComponent then
      begin
      Delete(i);
      Break;
      end;
  end;
end;


Метод GetOwner просто:
Код

function TTables.GetOwner: TComponent;
begin
Result:=FOwner;
end;


Проблема в том, что при удалении таблицы Notification не вызывается, таблица остается на месте и при попытке обращения AV. Что не так?

Автор: Fedia 28.12.2006, 02:21
Есть подозрение, что (Self.Collection as TTables).GetOwner у тебя не является объектом типа TAvgClassifierForm. В этом случае на строчке:
Код

NC:=TAvgClassifierForm((Self.Collection as TTables).GetOwner);
 AV может не появиться, но и соответственно TAvgClassifierForm.Notification не сработает.
Цитата(Beltar @  27.12.2006,  21:08 Найти цитируемый пост)
Проблема в том, что при удалении таблицы Notification не вызывается, таблица остается на месте и при попытке обращения AV. Что не так?

Таблица уничтожается, но поскольку TAvgClassifierForm.Notification не сработал и соответственно из коллекции элемент, ссылающийся на уничтоженную таблицу не был удален, то при обращении к этому элементу и получается AV.

Может тебе пример и не нужен, но вот простой вариант, в котором Notification срабатывает: 
Код

type
  TForm1 = class(TForm)
    Button3: TButton;
    ADOTable1: TADOTable;
    Memo1: TMemo;
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button3Click(Sender: TObject);
begin
  ADOTable1.FreeNotification(Form1);
  ADOTable1.Free;
end;

procedure TForm1.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if Operation = opRemove then
  Memo1.Lines.Add(AComponent.Name);
end;

end.

Автор: Beltar 28.12.2006, 08:51
Оказывается я забыл указать, что Notification у моего компонента д/б перекрытым. Если честно, попадаюсь на этом 2-й раз. Как-то раз я забыл перекрыть у компонента деструктор и потом только после проверки на утечки увидел, что код деструктора просто не генерировался.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)