![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Реализация интерфейса [D7, WinXP]
oleg___ © (2006-07-27 13:26:00)Как сделать, чтобы класс, реализующий интерфейс, не уничтожался автоматически при нулевом количестве ссылок на интерфейс?
Deka (2006-07-28 10:55:00) [1]IClassFactory::LockServer
Called by the client of a class object to keep a server open in memory, allowing instances to be created more quickly.
А это не то? Метод LockServer() фабрики классов не позволяет выгрузить COM-объект даже когда он не используется...
Юрий Зотов (2006-07-27 21:05:00) [2]> oleg___
Наверное, правильным, простым и удобным будет такое решение:
type
IFirst = interface(...)
...
end;
IInternalFirst = interface(IFirst)
... // Расширение IFirst для внутреннего использования
end;
TFirst = class(TAutoObject, IFirst, IInternalFirst)
...
end;
TSecond = class(TAutoObject, ISecond)
protected
FRef: IInternalFirst;
function Get_Ref: IFirst; safecall;
...
end;
oleg___ (2006-07-27 15:19:00) [3]
> Игорь Шевченко © (27.07.06 15:13) [20]
> А можно реализовать интерфейс в наследнике от TComponent
у меня com-сервер
Игорь Шевченко (2006-07-27 15:13:00) [4]А можно реализовать интерфейс в наследнике от TComponent
oleg___ (2006-07-27 15:11:00) [5]
> Юрий Зотов © (27.07.06 14:43) [16]
> Интерфейсную ссылку можно завести где угодно, не обязательно
> в массиве. Хоть в самом объекте TFirst - главное, чтобы
> _AddRef щелкнул. Можно даже и не заводить ссылку, а просто
> вызвать _AddRef в конструкторе TFirst. Хотя это и дурной
> стиль, но цель будет достигнута - объект перестанет уничтожаться
> автоматически.
Если просто вызывать AddRef возникают сложности с уничтожением объекта.
Насчет еще одного интерфейса - спасибо, попробую.
Джо (2006-07-27 14:50:00) [6]> [13] Romkin ©
Я тоже довольно часто так поступаю. В частности, когда нужно "привинтить" реализацию какого-то интерфейса к стандартному VCL-скому контролу. Часто это бывает форма, которой, разумеется, подсчет ссылок, как козе баян :) Оно, конечно, можно сделать, чтобы форма делегировала реализацию интерфейса какому-то другому классу; так, по-науке, оно, наверное было бы и правильнее, но — лень матушка :)
oleg___ (2006-07-27 14:46:00) [7]
> Медведъ (27.07.06 14:39) [15]
> вызвать AddRed при создании
имхо, вызывать AddRef без реальной ссылки может плохо кончится
Юрий Зотов (2006-07-27 14:43:00) [8]> oleg___ (27.07.06 14:22) [12]
Интерфейсную ссылку можно завести где угодно, не обязательно в массиве. Хоть в самом объекте TFirst - главное, чтобы _AddRef щелкнул. Можно даже и не заводить ссылку, а просто вызвать _AddRef в конструкторе TFirst. Хотя это и дурной стиль, но цель будет достигнута - объект перестанет уничтожаться автоматически.
Но строго говоря, возникновение подобной проблемы обычно указывает на недостаточную продуманность структуры классов и/или интерфейсов. Было бы лучше не прибегать к сомнительным решениям, а пересмотреть эту самую структуру. Например, можно ввести еще один интерфейс, используемый только во внутренних целях - и пусть TFirst реализует оба интерфейса (а он и так их фактически реализует). Тогда FRef (или их массив) в TSecond будет содержать ссылку на этот служебный интерфейс - и все тип-топ.
Медведъ (2006-07-27 14:39:00) [9]вызвать AddRed при создании
Romkin (2006-07-27 14:34:00) [10]oleg___ (27.07.06 13:44) [6] а для этого случая уже Зотов ответил.
По идеологии тебе вообще может понадобиться агрегация, тогда AddRef & Release TFirst должны дергать эти функции у TSecond.
Romkin (2006-07-27 14:31:00) [11]А если не извращаться? Достаточно перекрыть addref & release у кокласса.
IUnknown - это не класс! Ну нет у интерфейса реализации.
TMyObj = class(TComObject, IMyIntf)
public
function ObjAddRef: integer; stdcall; override;
function ObjRelease: integer; stdcall; override;
end;
...
function TMyObj.ObjAddRef: integer;
begin
Result := -1;
end;
function TMyObj.ObjRelease: integer;
begin
Result := -1;
end;
В случае TAutoObject - просто пишите свои функции _Addref & _Release - интерфейс подцепит.
И не надо только мудрить!
oleg___ (2006-07-27 14:22:00) [12]
> Юрий Зотов © (27.07.06 14:09) [11]
Да можно. Но в реальном проекте у меня массив таких объектных ссылок. Придется делать второй массив интерфейсных. Хотелось бы по-проще.
Юрий Зотов (2006-07-27 14:09:00) [13]> oleg___ (27.07.06 14:04) [10]
Это другое дело. Но ведь можно сделать две ссылки - одну объектную, а другую интерфейсную.
oleg___ (2006-07-27 14:04:00) [14]
> Юрий Зотов © (27.07.06 13:58) [9]
и доступа к членам класса TFirst тоже не будет, будет только к членам интерфейса IFirst.
Забыл сказать цель всего этого - у объекта TFirst есть свойства и методы, которые я не хочу светить в интерфейсе IFirst, но которые используются в классе TSecond.
Юрий Зотов (2006-07-27 13:58:00) [15]> oleg___ (27.07.06 13:44) [6]
TSecond = class(TAutoObject, ISecond)
protected
FRef: IFirst; // И объект уничтожаться не будет, т.к. на него висит ссылка
...
end;
oleg___ (2006-07-27 13:48:00) [16]....когда пользователь через Get_Ref получает указатель на интерфейс IFirst, а потом перестает его использовать, то объект FRef автоматически удаляется - в этом проблема.
@!!ex (2006-07-27 13:47:00) [17]Как видно класс наследуеться от IFirst.
А у того уже забито внутри свойство убиваться когда ссылки кончаються.
Возможно это можно обойти, но ИМХО врядли.
oleg___ (2006-07-27 13:44:00) [18]Объясню по-подробней: есть два класса, реализующие два интерфейса, причем второй класс создает внутри себя первый и предоставляет доступ к его интерфейсу через свое свойство.
Вот код (тестовый пример):
TFirst = class(TAutoObject, IFirst)
protected
public
constructor Create;
destructor Destroy; override;
end;
TSecond = class(TAutoObject, ISecond)
protected
FRef: TFirst; // ЭТОТ ОБЪЕКТ УНИЧТОЖАЕТСЯ АВТОМАТИЧЕСКИ, А ОН НУЖЕН
function Get_Ref: IFirst; safecall;
public
procedure Initialize; override;
destructor Destroy; override;
end;
....
@!!ex (2006-07-27 13:43:00) [19]Ruslan D
Не правильно думешь.
Это свойство не ООП, а класса IUnknown.
Ruslan D (2006-07-27 13:39:00) [20]Думаю что никак, т.к. это одно из свойст ООП. Это типа автоматическое управление памятью.