"EhLib.Com" https://forum.ehlib.com/ru/ |
|
Поле OwnsObject в TRefObjectField https://forum.ehlib.com/ru/viewtopic.php?f=4&t=2779 |
Страница 1 из 1 |
Автор: | istrebitel [ 24 май 2019, 01:08 ] |
Заголовок сообщения: | Поле OwnsObject в TRefObjectField |
Здравствуйте. Не могли бы вы добавить 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; |
Автор: | istrebitel [ 05 фев 2020, 01:03 ] |
Заголовок сообщения: | Re: Поле OwnsObject в TRefObjectField |
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; Хочется поставить галочку и не думать что забыл где то освободить объект. |
Автор: | EhLibSupport [ 07 фев 2020, 21:59 ] |
Заголовок сообщения: | Re: Поле OwnsObject в TRefObjectField |
Добрый день. OwnsObject в TStringList работает не однозначно. Код: StringList1 := TStringList.Create(True); Например, при присвоении Код: StringList1.Objects[0] := TObject.Create; старый объект не удаляется. Соответственно не до конца понятно, надо ли делать режим OwnsObject полностью совместимым с TStringList, или писать свой более правильный способ. В наших проектах мы в подобных случаях работаем с классами через интерфейсы и порожденными от TInterfacedObject. |
Автор: | istrebitel [ 10 фев 2020, 01:51 ] | ||
Заголовок сообщения: | Re: Поле OwnsObject в TRefObjectField | ||
Ну зачем копировать из 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;
|
Автор: | istrebitel [ 10 фев 2020, 05:35 ] |
Заголовок сообщения: | Re: Поле OwnsObject в TRefObjectField |
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 объявлены в секции имплементации, от них не унаследоваться. |
Автор: | EhLibSupport [ 10 фев 2020, 18:41 ] |
Заголовок сообщения: | Re: Поле OwnsObject в TRefObjectField |
Добрый день. Цитата: Да но как записать интерфейс в поле? Деструктор объекта должен вызываться при уничтожении последней ссылки на объект. В вашем случае это либо MemTableEh1.Free; либо MemTableEh1ref.Value := Null; |
Автор: | EhLibSupport [ 10 фев 2020, 18:49 ] |
Заголовок сообщения: | Re: Поле OwnsObject в TRefObjectField |
Добрый день. Цитата: В первом RefField поля хранят ссылки на TMemoryRecordEh второго. При отрисовке этих полей я стал искать способ быстрого позиционирования и понял что GotoRec и GotoBookmark работают перебором. Не очень понятно, зачем вам надо позиционироваться на запись, если у вас уже есть указатель на запись. С указателя вы можете напрямую обратиться к значению поля. Код: procedure TForm1.Button6Click(Sender: TObject);
var v: Variant; Rec: TMemoryRecordEh; begin Rec := MemTableEh1.Rec; v := Rec.DataValues['Continent', dvvValueEh]; end; |
Автор: | istrebitel [ 11 фев 2020, 01:21 ] | ||
Заголовок сообщения: | Re: Поле OwnsObject в TRefObjectField | ||
Ну в GetCellParams да, я там просто эксперементировал, но потом мне надо будет редактировать эту запись, и соответственно нужно будет туда спозиционироваться, так безопасно ли по Rec.Index работать? А по освобождению не понял как правильно сделать? На приложенном примере не получается.
|
Автор: | EhLibSupport [ 12 фев 2020, 07:24 ] |
Заголовок сообщения: | Re: Поле OwnsObject в TRefObjectField |
Добрый день. ---- Rec.Index можно использовать если в MemTable, где храниться запись, не используется фильтр, сортировка, удаление или перезагрузка данных. ---- В вашем примере вы используете код. MemTableEh1ref.Value := TTestObj.Create; где Value имеет тип property Value: TObject. Чтобы заработал механизм автоматического удаления объектов через Automatic Reference Counting важно сразу после создания объекта использовать его через ссылки на интерфейс. В вашем случае вместо поля TRefObjectField надо использовать поле TInterfaceField в котором property Value имеет тип IUnknown. |
Автор: | istrebitel [ 20 фев 2020, 09:39 ] |
Заголовок сообщения: | Re: Поле OwnsObject в TRefObjectField |
Поигрался с TInterfaceField, работает. Спасибо за подсказку. Правда вначале тупил почему при удалении строки не освобождается объект, потом понял что пару строчек кэшируются. EhLibSupport писал(а): Rec.Index можно использовать если в MemTable, где храниться запись, не используется фильтр, сортировка, удаление или перезагрузка данных. Ну у меня и с сортировкой работает (при клике по столбцу), Index'ы меняют свои значения, но храню то я не их, а сам TMemoryRecordEh. |
Страница 1 из 1 | Часовой пояс: UTC |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |