Components for Delphi and C++ Builder.

Перейти в английский форум
Перейти на EhLib.com
Текущее время: 28 мар 2024, 16:42

Часовой пояс: UTC




Начать новую тему Ответить на тему  [ Сообщений: 10 ] 
Автор Сообщение
 Заголовок сообщения: Поле OwnsObject в TRefObjectField
СообщениеДобавлено: 24 май 2019, 01:08 
Не в сети

Зарегистрирован: 16 фев 2018, 04:13
Сообщений: 54
Откуда: АО ОТЭКО
Здравствуйте.
Не могли бы вы добавить Boolean поле OwnsObject по аналогии TStringList в поле TRefObjectField, чтобы объекты уничтожались при удалении строки, закрытии датасета или присвоение нового объекта когда Value не nil.
А то надоедает писать
Код:
procedure TfrmTimeLines.mtMainBeforeDelete(DataSet: TDataSet);
begin
  mtMainStatusHistory_ic.Value.Free;
end;

procedure TfrmTimeLines.mtMainBeforeClose(DataSet: TDataSet);
begin
  if mtMain.Active then
  begin
    mtMain.Filtered := False;
    if not mtMain.IsEmpty then
    begin
      mtMain.First;
      while not mtMain.Eof do
      begin
        mtMainStatusHistory_ic.Value.Free;
        mtMain.Next;
      end;
    end;
  end;
end;


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Поле OwnsObject в TRefObjectField
СообщениеДобавлено: 05 фев 2020, 01:03 
Не в сети

Зарегистрирован: 16 фев 2018, 04:13
Сообщений: 54
Откуда: АО ОТЭКО
up
Сейчас использую
Код:
procedure FreeRefObjectFields(MemTableEh: TMemTableEh; OnlyCurrentRow: Boolean = False);
var
  Fields: TList<TRefObjectField>;
  Field: TField;
  I: Integer;
begin
  if (not MemTableEh.Active) or (OnlyCurrentRow and MemTableEh.IsEmpty) then
    exit;
  Fields := TList<TRefObjectField>.Create;
  try
    for Field in MemTableEh.Fields do
    begin
      if Field is TRefObjectField then Fields.Add(TRefObjectField(Field));
    end;
    if Fields.Count = 0 then
      exit;
    if OnlyCurrentRow then
    begin
      if not (MemTableEh.State in [dsEdit, dsInsert]) then MemTableEh.Edit;
      for I := 0 to Fields.Count - 1 do
      begin
        Fields[I].Value.Free;
        Fields[I].Value := nil;
      end;
      MemTableEh.Post;
    end else
    begin
      MemTableEh.Filtered := False;
      if not MemTableEh.IsEmpty then
      begin
        MemTableEh.First;
        while not MemTableEh.Eof do
        begin
          MemTableEh.Edit;
          for I := 0 to Fields.Count - 1 do
          begin
            Fields[I].Value.Free;
            Fields[I].Value := nil;
          end;
          MemTableEh.Post;
          MemTableEh.Next;
        end;
      end;
    end;
  finally
    Fields.Free;
  end;
end;

Хочется поставить галочку и не думать что забыл где то освободить объект.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Поле OwnsObject в TRefObjectField
СообщениеДобавлено: 07 фев 2020, 21:59 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1546
Добрый день.

OwnsObject в TStringList работает не однозначно.
Код:
  StringList1 := TStringList.Create(True);

Например, при присвоении
Код:
StringList1.Objects[0] := TObject.Create;

старый объект не удаляется.

Соответственно не до конца понятно, надо ли делать режим OwnsObject полностью совместимым с TStringList, или писать свой более правильный способ.

В наших проектах мы в подобных случаях работаем с классами через интерфейсы и порожденными от TInterfacedObject.

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Поле OwnsObject в TRefObjectField
СообщениеДобавлено: 10 фев 2020, 01:51 
Не в сети

Зарегистрирован: 16 фев 2018, 04:13
Сообщений: 54
Откуда: АО ОТЭКО
Ну зачем копировать из VCL плохое, конечно логичнее делать правильную обработку, хотя она немного трудозатратней. Мне бы и аналога StringList хватило, просто хочется режим создал объект и отдал его на откуп в DataSet. Ну если будут ресурсы, реализуйте пожалуйста.

Ещё вопросик не совсем по RefField. У меня есть 2 MemTabl'а.
В первом RefField поля хранят ссылки на TMemoryRecordEh второго. При отрисовке этих полей я стал искать способ быстрого позиционирования и понял что GotoRec и GotoBookmark работают перебором.

Код:
function TCustomMemTableEh.GotoRec(Rec: TMemoryRecordEh): Boolean;
begin
  Result := SetToRec(Rec);
end;

function TCustomMemTableEh.SetToRec(Rec: TObject): Boolean;
var
  i: Integer;
begin
  CheckActive;
  Result := False;
  for i := 0 to RecordsView.ViewItemsCount-1 do
    if RecordsView.ViewRecord[i] = Rec then
    begin
      RecNo := i+1;
      Result := True;
      Exit;
    end;
end;

procedure TCustomMemTableEh.InternalGotoBookmarkData(var BookmarkData: TBookmarkDataEh);
var
  ARecIdx: Integer;
  ARec: TMemoryRecordEh;
begin
  ARec := BookmarkData.MemRec;
  ARecIdx := RecordsView.IndexOfRec(ARec);
...
end;

function TRecordsViewEh.IndexOfRec(Rec: TMemoryRecordEh): Integer;
var
  i: Integer;
begin
  Result := -1;

  if ViewItemsCount = 0 then
    Exit;

  if ViewRecord[ViewItemsCount-1] = Rec then
    Result := ViewItemsCount-1
  else
  begin
    for i := 0 to ViewItemsCount-1 do
      if ViewRecord[i] = Rec then
      begin
        Result := i;
        Exit;
      end;
  end;
end;


Моментальная навигация только через RecNo. Так вот у меня вопрос если Filter не используется и все записи видимые безопасно ли использовать поле Index в TMemoryRecordEh или могут быть подводные камни? Сейчас использую так
Код:
procedure TfrmElectrRepsMain.DynamicColumnsGetCellParams(Sender: TObject;
  EditMode: Boolean; Params: TColCellParamsEh);
var
  Rec: TMemoryRecordEh;
  BgCellColor: TColor;
begin
  if Assigned(TRefObjectField(TColumnEh(Sender).Field).Value) then
  begin
    Rec := TMemoryRecordEh(TRefObjectField(TColumnEh(Sender).Field).Value);
    mtSteps.InstantReadEnter(Rec.Index);
    try
      Params.Text := mtStepsersp_endtime_plan.AsString;
      BgCellColor := GetBackGroundColor(mtStepsersp_endtime_plan.AsDateTime, mtStepsersp_endtime_fact.AsDateTime);
      if BgCellColor <> clDefault then
        Params.Background := BgCellColor;
    finally
      mtSteps.InstantReadLeave;
    end;
  end else
    Params.Text := '';
end;


Вложения:
RefFields.png
RefFields.png [ 52.65 KiB | Просмотров: 1549 ]
Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Поле OwnsObject в TRefObjectField
СообщениеДобавлено: 10 фев 2020, 05:35 
Не в сети

Зарегистрирован: 16 фев 2018, 04:13
Сообщений: 54
Откуда: АО ОТЭКО
EhLibSupport писал(а):
В наших проектах мы в подобных случаях работаем с классами через интерфейсы и порожденными от TInterfacedObject.

Да но как записать интерфейс в поле?

Код:
  TTestObj = class(TInterfacedObject)
  public
    destructor Destroy; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  tmp: IInterface;
begin
  MemTableEh1.Append;
  tmp := TTestObj.Create;
  MemTableEh1ref.Value := tmp; // Как произвести запись? Если tmp будет TTestObj, то не будет освобождения.
  MemTableEh1.Post;
end;

{ TTestObj }

destructor TTestObj.Destroy;
begin
  MessageBox(0, 'Bye', 'Bye', 0);
  inherited;
end;


TInterfacedObjectWrapper и IObjectRefInterface объявлены в секции имплементации, от них не унаследоваться.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Поле OwnsObject в TRefObjectField
СообщениеДобавлено: 10 фев 2020, 18:41 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1546
Добрый день.

Цитата:
Да но как записать интерфейс в поле?

Деструктор объекта должен вызываться при уничтожении последней ссылки на объект.

В вашем случае это либо
MemTableEh1.Free;
либо
MemTableEh1ref.Value := Null;

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Поле OwnsObject в TRefObjectField
СообщениеДобавлено: 10 фев 2020, 18:49 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1546
Добрый день.

Цитата:
В первом RefField поля хранят ссылки на TMemoryRecordEh второго. При отрисовке этих полей я стал искать способ быстрого позиционирования и понял что GotoRec и GotoBookmark работают перебором.

Не очень понятно, зачем вам надо позиционироваться на запись, если у вас уже есть указатель на запись.
С указателя вы можете напрямую обратиться к значению поля.

Код:
procedure TForm1.Button6Click(Sender: TObject);
var
  v: Variant;
  Rec: TMemoryRecordEh;
begin
  Rec := MemTableEh1.Rec;
  v := Rec.DataValues['Continent', dvvValueEh];
end;

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Поле OwnsObject в TRefObjectField
СообщениеДобавлено: 11 фев 2020, 01:21 
Не в сети

Зарегистрирован: 16 фев 2018, 04:13
Сообщений: 54
Откуда: АО ОТЭКО
Ну в GetCellParams да, я там просто эксперементировал, но потом мне надо будет редактировать эту запись, и соответственно нужно будет туда спозиционироваться, так безопасно ли по Rec.Index работать?


А по освобождению не понял как правильно сделать?
На приложенном примере не получается.


Вложения:
EhLibMemTableInterface.zip [54.88 KiB]
Скачиваний: 91
Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Поле OwnsObject в TRefObjectField
СообщениеДобавлено: 12 фев 2020, 07:24 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1546
Добрый день.

----
Rec.Index можно использовать если в MemTable, где храниться запись, не используется фильтр, сортировка, удаление или перезагрузка данных.

----
В вашем примере вы используете код.
MemTableEh1ref.Value := TTestObj.Create;
где Value имеет тип property Value: TObject.

Чтобы заработал механизм автоматического удаления объектов через Automatic Reference Counting важно сразу после создания объекта использовать его через ссылки на интерфейс.
В вашем случае вместо поля TRefObjectField надо использовать поле TInterfaceField в котором property Value имеет тип IUnknown.

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Поле OwnsObject в TRefObjectField
СообщениеДобавлено: 20 фев 2020, 09:39 
Не в сети

Зарегистрирован: 16 фев 2018, 04:13
Сообщений: 54
Откуда: АО ОТЭКО
Поигрался с TInterfaceField, работает. Спасибо за подсказку.
Правда вначале тупил почему при удалении строки не освобождается объект, потом понял что пару строчек кэшируются.
EhLibSupport писал(а):
Rec.Index можно использовать если в MemTable, где храниться запись, не используется фильтр, сортировка, удаление или перезагрузка данных.

Ну у меня и с сортировкой работает (при клике по столбцу), Index'ы меняют свои значения, но храню то я не их, а сам TMemoryRecordEh.


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 10 ] 

Часовой пояс: UTC


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5


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

Найти:
Перейти:  
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB