Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TForm + IMyInterface, Простой вызов форм через interfaces 
:(
    Опции темы
Illusion Dolphin
Дата 7.11.2012, 22:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



Есть проект, в нём много форм. Было решено чтобы формы реализовывали интерфейсы и доступ к формам был через интерфейсы. Внешне это выглядит так:
Код

type
  //для всех форм общее
  IFormInterface = interface
    ['{24769E47-FE80-4FF7-81CC-F8E6C8AA77EC}']
    procedure Show;
  end;

  //интерфейс для формы
  IRequestPasswordForm = interface(IFormInterface)
    ['{7710EB12-321A-44B1-B72A-FD238C450ACD}']
    function ForImage(FileName: string): string;
  end;

Код

//вспомагательная функция
function RequestPasswordForm: IRequestPasswordForm;

...

function RequestPasswordForm: IRequestPasswordForm;
begin
  Result := FormInterfaces.CreateForm<IRequestPasswordForm>();
end;

...
//функция для создания обхекта, реализующего интерфейс
function TFormInterfaces.CreateForm<T>: T;
var
  G: TGUID;
  F: TForm;
begin
  G := GetTypeData(TypeInfo(T))^.Guid;
  //FFormInterfaces - получает класс формы по GUID интерфейса, формы регистрируются в TFormInterfaces
  Application.CreateForm(FFormInterfaces[G], F);

  F.GetInterface(G, Result);
end;


И использование вот такое:
Код

procedure proc;
begin
  Password := RequestPasswordForm.ForImage(FileName);
end;


Форма, реализующая IRequestPasswordForm - модальная, и по закрытю формы она освобождается:
Код

procedure TPassWordForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;


Всё даже работало(хотя не должно было) до сегодня. Получается интереснейший баг:
  Password := RequestPasswordForm.ForImage(FileName); - срабатывает прекрасно, после этой строки форма уничтожается сама
end; <-- а тут получается очень плохо :( Делфи видит, что интерфейс выходит из области видимости и делает ему _Release, но объет уже не существует, получаем ошибку доступа. 
Был вариант по закрытию окна его прятать и считать самостоятельно число ссылок через _AddRef _Release, но они реализованы в TComponent и они не виртуальные - т.е. я не могу их дописать. 

Есть ли идеи как оставить такую красоту как "Password := RequestPasswordForm.ForImage(FileName);" и избежать проблемы со счётчиком ссылок?

Заранее спасибо!


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
MetalFan
Дата 8.11.2012, 07:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



Цитата(Illusion Dolphin @  7.11.2012,  22:44 Найти цитируемый пост)
Был вариант по закрытию окна его прятать и считать самостоятельно число ссылок

И чем не вариант? только зачем что-то там самостоятельно считать? Скрыли форму, как интерфейс выйдет за пределы видимости, форма уничтожится...


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Illusion Dolphin
Дата 8.11.2012, 08:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



Цитата

только зачем что-то там самостоятельно считать?

Я плохо выразился. TForm уже имплементирует IInterface, эта реализация сделана в TComponent, её-то я и думал использовать, но не смог т.к. методы (_AddRef _Release) не виртуальные. Сейчас я второй раз реализую интерфейc IInterface в моей форме:
Код

    function IInterface.QueryInterface = QueryInterfaceInternal;
    function QueryInterfaceInternal(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;

Я только не в курсе, корректно ли это - 2 раза один и тот же интерфейс реализовывать - не будет ли в будущем проблем?


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
MetalFan
Дата 8.11.2012, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



хм, а если класс, реализующий твой интерфейс для формы, наследовать не от TForm, а от TInterfacedObject, а внутри уже просто создавать/прибивать форму?


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Illusion Dolphin
Дата 8.11.2012, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



Цитата

хм, а если класс, реализующий твой интерфейс для формы, наследовать не от TForm, а от TInterfacedObject, а внутри уже просто создавать/прибивать форму? 


Это будет работать конечно, но не хотелось бы плодить ненужные сущности.

Моя вторая имплементация интерфейса - работает, я в ней вызываю те же методы, что и первая реализация (благо они protected). Просто вопрос в том, как делфи работает если 2 раза реазилуется один и тот же интерфейс, не будет ли потенциально какой-нибудь ошибки, о которой я не знаю?

P.S. Пока что я подумал - и вроде бы всё корректно должно быть, но так бы хотелось чтобы кто-нить подтвердил моё предположение...

Это сообщение отредактировал(а) Illusion Dolphin - 8.11.2012, 10:39


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
bems
Дата 15.11.2012, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



работает до тех пор, пока владелец формы не попытается ее уничтожить, уже после удаления при достижении счетчиком ссылок нуля
можно обойти вызов _Release сделав как-то так
Код

var
  Iface: IRequestPasswordForm;
begin
  Iface := RequestPasswordForm;  
  Password := Iface.ForImage(FileName);
  Pointer(Iface) := nil;



Это сообщение отредактировал(а) bems - 15.11.2012, 12:38


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Illusion Dolphin
Дата 15.11.2012, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



Цитата

  Iface := RequestPasswordForm;  
  Password := Iface.ForImage(FileName);
  Pointer(Iface) := nil;

Этого я и пытаюсь избежать - слишком неудобно. В итоге остановится на том, что когда мой счётчик ссылок выходит на ноль, я делаю Release, что безопасно осбовождает форму через сообщение - в этом случае, вроде как, теоретически, не будет AV.


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
Alexeis
Дата 16.11.2012, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



  Если комовское управление памятью мешает, то я делаю свои виртуальные AddRef и Release которые возвращают значения соответственно 2 и 1 всегда, а внутри ничего не делают, а объект уничтожаю сам. С точки зрения COM такое поведение вполне корректно, получается так как если бы создавалась своя внутренняя копия указателя, которая уничтожается в нужное тебе время.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
bems
Дата 16.11.2012, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Цитата(Alexeis @  16.11.2012,  00:00 Найти цитируемый пост)
Если комовское управление памятью мешает, то я делаю свои виртуальные AddRef и Release которые возвращают значения соответственно 2 и 1 всегда, а внутри ничего не делают, а объект уничтожаю сам. С точки зрения COM такое поведение вполне корректно, получается так как если бы создавалась своя внутренняя копия указателя, которая уничтожается в нужное тебе время. 
реализация этих методов у TComponent что-то такое и делает

Цитата(Illusion Dolphin @  15.11.2012,  23:26 Найти цитируемый пост)
 В итоге остановится на том, что когда мой счётчик ссылок выходит на ноль, я делаю Release, что безопасно освобождает форму через сообщение - в этом случае, вроде как, теоретически, не будет AV. 

да, посмотрел сейчас, при уничтожении компонента он сообщает об этом владельцу. Не пойму откуда я взял что это проблема. Видимо когда-то очень давно в какой-то очень старой версии так оно и было smile


--------------------
Обижено школьников: 8
PM MAIL   Вверх
lomaster
Дата 16.11.2012, 10:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 27.5.2012

Репутация: нет
Всего: 2



А зачем делать Action := caFree;?
PM   Вверх
Illusion Dolphin
Дата 16.11.2012, 22:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



Цитата

А зачем делать Action := caFree;? 

Это означает что после закрытия форма будет безопасно уничтожена. caHide - просто спрятана и может быть ещё потом показана итд.

Добавлено через 2 минуты и 44 секунды
В моём финальном решении caFree нету, это было одной из причин проблемы в такой архитектуре.


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
lomaster
Дата 16.11.2012, 23:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 27.5.2012

Репутация: нет
Всего: 2



Цитата

это было одной из причин проблемы в такой архитектуре.
 Вот, вот. Это 2 разных подхода.
PM   Вверх
bems
Дата 17.11.2012, 13:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



А зачем в этой задаче вообще интерфейсы?


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Illusion Dolphin
Дата 17.11.2012, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



Цитата

А зачем в этой задаче вообще интерфейсы? 

Было много зависимостей между формами, убирал зависимости между модулями, в том числе и циклические. Пытался черпануть идеологию из DI/IoC (на .net MVC модная штуковина). 

Это сообщение отредактировал(а) Illusion Dolphin - 17.11.2012, 14:05


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0685 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.