Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.145.111.125] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Решил создать для себя класс для того чтобы скрыть в приложении детали соединения и общения с базой. Для этого создаю :
unit baseconnector; interface uses rwindows,forms,sysutils,classes,IBDatabase, DB, IBCustomDataSet, IBQuery, datamodule1 ; type TBaseConnector= class private public app2:TApplication; constructor Create(app:TApplication); destructor Destroy; override; function getallparameters(groupid:integer;parnamelist,parvallist,pargrouplist:tstringlist):integer; end; implementation constructor TBaseConnector.Create(app:TApplication); begin app.CreateForm(TDataModule2, DataModule2); app2:=app; end; destructor TBaseConnector.Destroy; begin //dATAMODULe2.DestroyComponents; // Datamodule2.Free;//ошибка Invalid Pointer Operation inherited; end; end. Не знаю, может делаю через задницу но для того чтобы не париться с ручным созданием IBDatabase, Ibtransaction и т.д ... решил использовать tdatamodule чтобы накидать туда компонентов а его уже юзать через TBaseConnector. unit datamodule1; interface uses SysUtils, Classes, IBDatabase, DB, IBCustomDataSet, IBQuery; type TDataModule2 = class(TDataModule) IBDatabase1: TIBDatabase; IBTransaction1: TIBTransaction; IBQuery1: TIBQuery; IBDataSet1: TIBDataSet; private { Private declarations } public { Public declarations } end; var DataModule2: TDataModule2; implementation {$R *.dfm} end. Вопрос в том как уничтожить экземпляр Datamodule2? |
Сообщ.
#2
,
|
|
|
TBaseConnector сделай интерфейсом, в дата модуле реализуй его...
|
Сообщ.
#3
,
|
|
|
Цитата cyberovskij @ Datamodule2.Free;//ошибка Invalid Pointer Operation Потому что он в этот момент уже уничтожен. 1) для того что бы узнать что компонент уничтожается у TCompenent есть событие Notification 2) компонент автодеструктурируется если уничтожается его владелец. (в данном случаи его владельцем будет app: TApplication). 3) |
Сообщ.
#4
,
|
|
|
Цитата ViktorXP @ 3) |
Сообщ.
#5
,
|
|
|
Цитата cyberovskij @ Не знаю, может делаю через задницу но для того чтобы не париться с ручным созданием IBDatabase, Ibtransaction и т.д ... для того чтобы скрыть в приложении детали Не сомневайся, именно так ты и поступаешь. Ну и что такого сложного: задать имя базы данных. |
Сообщ.
#6
,
|
|
|
Цитата 05772 @ Ну и что такого сложного: задать имя базы данных. Может и действительно ничего сложного для ( нескольких_database+ нескольких_ibtransaction+ нескольких_десятков_датасетов)*нескольких_десятков_дефолтных_значений. |
Сообщ.
#7
,
|
|
|
А зачем уничтожать датамодуль, скажи, пожалуйста. Сильно мешает?
|
Сообщ.
#8
,
|
|
|
Цитата Fr0sT @ А зачем уничтожать датамодуль, скажи, пожалуйста. Сильно мешает? А зачем освобождают ненужные ресурсы? |
Сообщ.
#9
,
|
|
|
cyberovskij так он у тебя нормально при выгрузке приложения освободится и без твоего участия. Зачем это делать руками?
|
Сообщ.
#10
,
|
|
|
Но если надо ручками тоже можно. А почему бы и нет?
Надо просто отслежитвать корректно освобождение "старндартной" var DataModule2. Например, таким макаром: unit datamodule1; type TDataModule2 = class // (?) странно что в Unit "DataModule1" находится TDataModule2, может быть их сделать с одинаковыми номерами? ... public ... destructor Destroy; override; end; ... var DataModule2: TDataModule2; implemenation ... destructor TDataModule2.Destroy; begin if Self = DataModule2 then DataModule2 := nil; inherited; end; ... end. а освообождение выполнять не "диким" способом DataModule2.Free; а аккуратно: FreeAndNil(DataModule2); чтобы в случае, когда DataModule2 уже почил, не получить "NULL Pointer Exception" |
Сообщ.
#11
,
|
|
|
Цитата RuSA @ Надо просто отслежитвать корректно освобождение "старндартной" var DataModule2. более безопаснее будет заюзать Notification. да и более удобно. можно выполнить какое то действие в сам момент уничтожения |
Сообщ.
#12
,
|
|
|
Если юзать FreeAndNil, то if Self = DataModule2 then DataModule2 := nil; - излишне
|
Сообщ.
#13
,
|
|
|
Совсем нет.
Цитата Fr0sT @ Если юзать FreeAndNil, то if Self = DataModule2 then DataModule2 := nil; - излишне Наличие проверки в деструкторе, гарантирует очистку становящейся некорректной var-переменной. Ведь никто не гарантирует, что все виды освобождений будут проходить именно через FreeAndNil !? Цитата ViktorXP @ более безопаснее будет заюзать Notification. да и более удобно. можно выполнить какое то действие в сам момент уничтожения Интересно чем безопаснее? Завязка на Notification нужна там, где вводится синоним. Прич1м изящно это можно сделать, если класс обладатель синонима будет потомком TComponent (у которого есть Notification). Т.е. если бы в модуле TBaseConnector была своя копия указателя, то тогда надо было бы иметь Notification. Т.е. примерно так: type TBaseConnector = class(TComponent) ... private FDM: TDataModule2; ... procedure setDM( adm: TDataModule2); ... protected ... procedure Notification(AComponent: TComponent; Operation: TOperation); override; ... public property DM: TDataModule2 read FDM write setDM; end; implementation ... procedure TBaseConnector.Notification(AComponent: TComponent; Operation: TOperation); begin inherited; if Operation = opRemove then begin if AComponent = Self.FDM then Self.FDM := nil; end; end; procedure TBaseConnector.setDM( adm: TDataModule2); begin if (FDM <> adm) then begin FDM := adm; if (adm <> nil) then adm.FreeNotofication(Self); end; end; ... end. Такой метод применять для самого TDataModule очевидно, слишком длино. В деструкторе это смотрится гораздо логичнее, тем более что DataModule2 это unit-перменная, а не поле экземпляра класса (instance-field). |
Сообщ.
#14
,
|
|
|
Цитата RuSA @ Интересно чем безопаснее? никогда не нарвешся на мертвую ссылку. и тогда даже задумываться не будешь насчет Цитата RuSA @ Наличие проверки в деструкторе, гарантирует очистку становящейся некорректной var-переменной. Ведь никто не гарантирует, что все виды освобождений будут проходить именно через FreeAndNil !? пс. и его вообще можно конструировать в этом контейнере по запросе. |
Сообщ.
#15
,
|
|
|
Честно говоря думая что я не докнца понял что Вы хотели сказать, но вот есть такие соображения:
1) FreeAnlNil(X) удобнее простого X.Free вот чем: а) если освобождаемая переменная X уже nil, то FreeAndNil выполнится без ошибок, а Free даст "NULL Pointer", б) после выполнения освобождения, надо очичать X, иначе там останется "битая ссылка". FreeAndNil после своего выполнения выставит nelf nil, Free - нет. в) если перед выполнением операций в X уже ссылка битая (т.е. X <> nil, но сама перменная освобождена), оба варианта дадут нерпедсказуемые проблемыи в этом они схожи. 2) по-поводу никогда не нарвешся на мертвую ссылку Цитата ViktorXP @ никогда не нарвешся на мертвую ссылку это слишком громко сказано, т.к. в достаточно большом или старом проекте, нельзя гарантировать, что использования всегда будут "академически правильными". Так что простые "FreeAnNil", как показывает практика, достаточно просто позволят локализовать подобные ошибки. И вопрос корректного отслеживания ссылок в языках с отсутствием встроенного "сборщика мусора" вообще большая проблема. Вариант с обычным Notification проходит удобно только для синонимов внутри классов-потомков TCompoment, для других классов надо в каждом случае думать как это сделать безопасно. В исходном варианте проблема была в том, что в момент вызова Datamodule2.Free;//ошибка Invalid Pointer Operation Вот такие соображения. |