Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Интерфейсы и самоуничтожение  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13863
Это касается приложения типа UniGUI. Сам автор советует использовать интерфейсы.
Задача. Создать глобальные списки, использовать их в разных местах программы и не заботиться об их уничтожении.
Сразу напишу, что уничтожение объектов в UniMainModule.Destroy делать нельзя, т.к. при перезагрузке страницы может произойти так, что сразу за событием OnCreate выполнится из предыдущей веб-сессии событие OnDestroy.

Основное назначение зачем я это делаю - это, чтобы по 100500 раз их (списки) не наполнять, т.к. это списки, которые часто используются в событиях прорисовки таблиц.

В общем, получается так, что при закрытии приложения вываливается сообщение об утечках памяти, а их быть не должно.

Так вот. В классе есть два объекта (два списка TObjectDictionary). Проблема в том, что интерфейсы не могут иметь поля (переменные VAR), т.е. в интерфейс нельзя вставить TObjectDictionary в виде объекта а-ля VAR или свойства, поэтому пришлось объявить TObjectDictionary как результат функции. Не знаю, правильно ли это, т.е. две функции возвращают эти самые два объекта-списка типа TObjectDictionary. Списки один раз наполняются и используются глобально в разных формах приложения. В конце концов списки должны самоуничтожиться. В конструкторе класса вызываю методы создания и наполнения списков. В деструкторе соответственно уничтожение списков.

Ставил бряку внутри Destroy - бряка не срабатывает :( т.е. списки (TObjectDictionary) вместе со своими внутренними объектами не уничтожаются.

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

Вот весь модуль интерфейса и класса:
+

unit uKvxListsStyles;

interface

uses
  System.Generics.Collections, uniGUITypes;

type

  IKvxListsStyles = interface
    ['{5884A1CA-1DB7-49EB-B479-088EF15FB621}']

    function StylesTypesList: TObjectDictionary<Integer, TUniCellAttribs>;
    function StylesRegionsList: TObjectDictionary<Integer, TUniCellAttribs>;

    procedure FillTypesStyles;
    procedure FillRegionsStyles;
  end;



  TKvxListsStyles = class(TInterfacedObject, IKvxListsStyles)
  private
     TypesList: TObjectDictionary<Integer, TUniCellAttribs>;
     RegionsList: TObjectDictionary<Integer, TUniCellAttribs>;

    procedure FillTypesStyles;
    procedure FillRegionsStyles;

  public
     function StylesTypesList: TObjectDictionary<Integer, TUniCellAttribs>;
     function StylesRegionsList: TObjectDictionary<Integer, TUniCellAttribs>;
     constructor create;
     destructor Destroy;
  end;

//var
//  KvxListsStyles: IKvxListsStyles;

implementation

uses MainModule;

{ KvxListsStyles }

constructor TKvxListsStyles.create;
begin
  FillTypesStyles;
  FillRegionsStyles;
end;


destructor TKvxListsStyles.Destroy;
begin
  if Assigned(TypesList) then
  begin
    TypesList.Clear;
    TypesList.Free;
  end;

  if Assigned(RegionsList) then
  begin
    RegionsList.Clear;
    RegionsList.Free;
  end;
end;

procedure TKvxListsStyles.FillRegionsStyles;
Var
  Attribs: TUniCellAttribs;
begin
  if Not Assigned(RegionsList) then
    RegionsList := TObjectDictionary<Integer, TUniCellAttribs>.Create([doOwnsValues])
  else
    RegionsList.Clear;
// потом в цикле наполняю список

  RegionsList.Add(0, TUniCellAttribs.Create(True));
  RegionsList.Items[0].Font.Color := -1;

  UniMainModule.qRegionsGetSTATEINDEX.open;
  if UniMainModule.qRegionsGetSTATEINDEX.RecordCount <= 0 then exit;
  while not UniMainModule.qRegionsGetSTATEINDEX.Eof do
  begin
    Attribs := TUniCellAttribs.Create(True);
    Attribs.Font.Color := UniMainModule.qRegionsGetSTATEINDEXSTATEINDEX.Value;

    RegionsList.Add(UniMainModule.qRegionsGetSTATEINDEXID.Value, Attribs);
    UniMainModule.qRegionsGetSTATEINDEX.Next;
  end;// while

  UniMainModule.qRegionsGetSTATEINDEX.close;
end;

procedure TKvxListsStyles.FillTypesStyles;
Var
  Attribs: TUniCellAttribs;
begin
  if Not Assigned(TypesList) then
    TypesList := TObjectDictionary<Integer, TUniCellAttribs>.Create([doOwnsValues])
  else
    TypesList.Clear;

  TypesList.Add(0, TUniCellAttribs.Create(True));
  TypesList.Items[0].Font.Color := -1;

  UniMainModule.qTypesGetSTATEINDEX.open;
  if UniMainModule.qTypesGetSTATEINDEX.RecordCount <= 0 then exit;
  while not UniMainModule.qTypesGetSTATEINDEX.Eof do
  begin
    Attribs := TUniCellAttribs.Create(True);
    Attribs.Font.Color := UniMainModule.qTypesGetSTATEINDEXSTATEINDEX.Value;

    TypesList.Add(UniMainModule.qTypesGetSTATEINDEXID.Value, Attribs);
    UniMainModule.qTypesGetSTATEINDEX.Next;
  end;// while

  UniMainModule.qTypesGetSTATEINDEX.close;

end;

function TKvxListsStyles.StylesRegionsList: TObjectDictionary<Integer, TUniCellAttribs>;
begin
  result := RegionsList;
end;

function TKvxListsStyles.StylesTypesList: TObjectDictionary<Integer, TUniCellAttribs>;
begin
  result := TypesList;
end;

end.




вот так использую, это просто для тестирования при старте главного модуля приложения создаю KvxListsStyles

procedure TUniMainModule.XXXXXXX;
var
  KvxListsStyles: IKvxListsStyles;
begin
    KvxListsStyles := TKvxListsStyles.Create;
end;



Модет быть неправильно то, что сделал TObjectDictionary в виде результата функции? Может надо объявить их как отдельные глобальные переменные?

Спасибо.

К сообщению приложен файл. Размер - 27Kb
8 фев 20, 01:18    [22075879]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейсы и самоуничтожение  [new]
asviridenkov
Member

Откуда:
Сообщений: 3975
X11,

Destroy таки должен быть override.
8 фев 20, 01:30    [22075883]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейсы и самоуничтожение  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13863
О! Спасибо!
8 фев 20, 10:02    [22075916]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейсы и самоуничтожение  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11498
X11
в интерфейс нельзя вставить TObjectDictionary в виде объекта а-ля VAR или свойства
Свойства объявлять можно. Но геттер и сеттер такого свойства должны быть методы этого интерфейса

X11
  IKvxListsStyles = interface
    ['{5884A1CA-1DB7-49EB-B479-088EF15FB621}']

    function StylesTypesList: TObjectDictionary<Integer, TUniCellAttribs>;
    function StylesRegionsList: TObjectDictionary<Integer, TUniCellAttribs>;

    procedure FillTypesStyles;
    procedure FillRegionsStyles;
  end;
выделенных методов в интерфейсе быть не должно. Это приватные методы класса

Вместо этой простыни
X11
destructor TKvxListsStyles.Destroy;
begin
  if Assigned(TypesList) then
  begin
    TypesList.Clear;
    TypesList.Free;
  end;

  if Assigned(RegionsList) then
  begin
    RegionsList.Clear;
    RegionsList.Free;
  end;
end;
достаточно написать
destructor TKvxListsStyles.Destroy;
begin
  TypesList.Free;
  RegionsList.Free;
  inherited Destroy;  // не забываем о родителях
end;
код будет абсолютно равнозначный.

Ну и еще, чтобы избежать неявной модификации списков, я бы делал так
  IKvxList = interface
    ['{A3333E27-6DBA-4792-B2B6-27CF6170DB0F}']
    function GetItem(AIdx: Integer): TUniCellAttribs;
  end;

  IKvxListsStyles = interface
    ['{5884A1CA-1DB7-49EB-B479-088EF15FB621}']
    function StylesTypesList: IKvxList;
    function StylesRegionsList: IKvxList;
  end;
10 фев 20, 15:25    [22076872]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейсы и самоуничтожение  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13863
_Vasilisk_,

спасибо
10 фев 20, 15:32    [22076880]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить