Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.03.05;
Скачать: CL | DM;

Вниз

Как получить объект по интерфейсу?   Найти похожие ветки 

 
Mx   (2005-04-22 17:16) [0]

Привет, Мастера! Согласно "ребрендингу" поменял свой ник, который и мне порядочно надоел, но это к делу не относится...

Вопрос может совсем дикий, но он в названии (ламером прошу не обзывать). Имеем переменную типа IUnknown, можно ли получить ссылку на сам объект? Или эта ссылка и есть то, что мне надо?


 
VMcL ©   (2005-04-22 17:21) [1]

>>Mx   (22.04.05 17:16)

QueryInterface
?


 
Mx   (2005-04-22 17:23) [2]

Так эээ вроде QueryInterface возвращает указатель на интерфейс, а мне надо наоборот, типа "QueryObject"...


 
DiamondShark ©   (2005-04-22 17:30) [3]

В общем виде -- никак.
За интерфейсом может не скрываться вообще никакого "объекта".

Что значит "сам объект"?


 
Mx   (2005-04-22 17:36) [4]

"Сам объект" - это то бишь тот, кто реализует. В-общем есть два объекта, но один о другом знает только по интерфейсу (а точнее у него список интерфейсов в IInterfaceList), но мне нужно получить в одном местечке указатель на объект, чтобы проверить значение его свойства. Конечно, можно свойство в интерфейсе описать, но так абстракция теряется, чего не хотелось бы... Хранить список объектов мне неудобно.

Так походу нельзя, угу?

type
...
 TImplementer = class(TObject, IInterface)
...

var
 I: IInterface;
begin
 ...
 if TImplementer(I).SomeProp then...
 ...
end;


 
DiamondShark ©   (2005-04-22 17:45) [5]

Реализующий интерфейс объект ты сам пишешь, или он уже есть сторонний?


 
Mx   (2005-04-22 18:01) [6]

Нет, оба пишу сам. Один - хранит списки экземпляров другого, а вернее список одного из интерфейсов этих экземпляров. Во многом это ради удобства и абстракции, но в принципе можно хранить и сами объекты...

P.S. Я прикинул, наверное, такое свойство и интерфейсу нужно, потому как будет еще сторонняя прога, которая с этим делом будет работать и там иногда эта инфа тоже понадобится, так что вынесу свойство в интерфейс.


 
Mx   (2005-04-22 18:04) [7]

А все-таки? И как из переменной A получить указатель на B или они все-таки не отличаются?

var
 A: IInterface;
 B: TInterfacedObject;
begin
 B := TInterfacedObject.Create;
 ...
 A := B as IInterface;
 ...
end;


 
Набережных С. ©   (2005-04-22 18:08) [8]


> Mx   (22.04.05 17:36) [4]

Даже если объект твой, все равно не надо так делать, ибо противоречит самой концепции интерфейса, а такие нарушения рано или поздно выходят боком. Тем более, что предоставив через интерфейс доступ к объекту ты тем самым как раз и уничтожишь его абстрагированность. Напротив, добавив в интерфейс метод проверки интересующего свойства ты ничего не теряешь. Просто те объекты, которые такого свойства не имеют, будут возвращать результатом этого метода E_NOTIMPL. Вполне обычная практика.

> Mx   (22.04.05 18:04) [7]

Да, так нормально. И они отличаются:)


 
DiamondShark ©   (2005-04-22 18:10) [9]


> Нет, оба пишу сам.

Тогда можно использовать приватный интерфейс как backdoor:

IBackdoor = interface
["{B094B0E6-ADE3-4818-8165-3F9F99123EC8}"]
function GetObject: TObject;
end;

TMyImpl = class(TObject, IInterface, IBacdoor)
...
end;


 
Skier ©   (2005-04-22 18:10) [10]

Примерно так :

IYourInterface = interface(...)
["{C9FC9806-2C28-4C3E-B265-C441398AC574}"]
function GetInstance : TObject;
property Instance : TObject read GetInstance; //"слабая" ссылка
end;


 
MBo ©   (2005-04-22 18:13) [11]

оно?


function GetImplementingObject(const I: IInterface): TObject;
const
 AddByte = $04244483; // opcode for ADD DWORD PTR [ESP+4], Shortint
 AddLong = $04244481; // opcode for ADD DWORD PTR [ESP+4], Longint
type
 PAdjustSelfThunk = ^TAdjustSelfThunk;
 TAdjustSelfThunk = packed record
   case AddInstruction: longint of
     AddByte : (AdjustmentByte: shortint);
     AddLong : (AdjustmentLong: longint);
 end;
 PInterfaceMT = ^TInterfaceMT;
 TInterfaceMT = packed record
   QueryInterfaceThunk: PAdjustSelfThunk;
 end;
 TInterfaceRef = ^PInterfaceMT;
var
 QueryInterfaceThunk: PAdjustSelfThunk;
begin
 Result := Pointer(I);
 if Assigned(Result) then
   try
     QueryInterfaceThunk := TInterfaceRef(I)^.QueryInterfa­ceThunk;
     case QueryInterfaceThunk.AddInstruc­tion of
       AddByte: Inc(PChar(Result), QueryInterfaceThunk.Adjustment­Byte);
       AddLong: Inc(PChar(Result), QueryInterfaceThunk.Adjustment­Long);
       else     Result := nil;
     end;
   except
     Result := nil;
   end;
end;

Hallvard Vassbotn


 
Mx   (2005-04-22 18:13) [12]

Спасибо, мужики, все узнал что хотел. Добавлю свойство в интерфейс, а то в натуре какой-то огород получается ненужный.

P.S. А с IBackdoor"ом прикольно! Взял на заметку.


 
Skier ©   (2005-04-22 18:20) [13]

>MBo ©   (22.04.05 18:13) [11]
Классно ! Это откуда ?


 
Набережных С. ©   (2005-04-22 18:40) [14]


> MBo ©   (22.04.05 18:13) [11]

Ай-я-яй! Чистое хакерство, как не стыдно!?
:))))))
Присоединяюсь к Skier ©   (22.04.05 18:20) [13]. Действительно классно!


 
MBo ©   (2005-04-22 20:08) [15]

>Это откуда ?
из borland-овских ньюсгрупп, 2002 год, автор указан.
Интересно, что функция была в виде задачи - Что оно делает?- (идентификаторы приводились несамообъясняющие)


 
vuk ©   (2005-04-22 20:43) [16]

to MBo:
Оно конечно да, достать можно. ТОлько для нормальной работы интерфейс должен быть гарантированно реализован классом Delphi. А иначе можно такого надоставать, что мало не покажется. Уж лучше IBackdoor. Во всяком случае спасает от упадания лицом в салат. Кстати, в VCL как раз такой способ используется - TComponent реализует IInterfaceComponentReference.


 
Mx   (2005-04-23 11:48) [17]


> vuk ©   (22.04.05 20:43) [16]
>
> ТОлько для нормальной работы
> интерфейс должен быть гарантированно реализован классом
> Delphi.
>


Помнится в справке Delphi я встречал, что объект в памяти формируется с соблюдением совместимости с COM. Наверняка, объекты других языков тоже таковы, потому код (хотя я там мало что понял) скорее всего универсальный.


 
DiamondShark ©   (2005-04-23 12:59) [18]


> Наверняка, объекты других языков тоже таковы, потому код
> (хотя я там мало что понял) скорее всего универсальный.

За интерфейсом может не стоять вообще никакого "объекта" в классическом понимании.


 
Mx ©   (2005-04-23 13:08) [19]


> DiamondShark ©   (23.04.05 12:59) [18]
>
> За интерфейсом может не стоять вообще никакого "объекта"
> в классическом понимании.

Я имел ввиду случай, когда есть переменная, ссылающаяся на какой-либо интерфейс какого-либо объекта


 
MBo ©   (2005-04-23 14:49) [20]

>vuk ©   (22.04.05 20:43) [16]
Конечно, при использовании любых хакерских недокументированных штучек автор должен себе отдавать отчет о риске и о границах применимости.

Про IBackDoor - что имелось в виду - техника, использованная в TComponent.IntfGetComponent - со введением специального интерфейса именно для обеспечения возможности Subj-евой цели?


 
Набережных С. ©   (2005-04-23 16:10) [21]


> Mx ©   (23.04.05 13:08) [19]

Что-то ты где-то не там читал. Или не так понял. Даже когда есть ссылка "на какой-либо интерфейс какого либо объекта". Ибо спецификация COM не устанавливает ни малейших ограничений на РЕАЛИЗАЦИЮ интерфейса. И уж тем более не устанавливает НИКАКИХ правил формирования структуры объекта.


 
Mx ©   (2005-04-23 16:29) [22]

Кажется я понял что имеется ввиду (про отсутствие объекта).


 
Набережных С. ©   (2005-04-23 16:48) [23]


> MBo ©   (23.04.05 14:49)
> техника, использованная в TComponent.IntfGetComponent

Имхо, эта "техника" столь же очевидная, сколь и неправильная. И IntfGetComponent ввели, я убежден, как заплатку, предназначив для чисто внутреннего использования.

А код в [11] действительно красивый. Сам по себе, безотносительно к каким-либо теориям:)


 
vuk ©   (2005-04-25 19:12) [24]

to Mx ©   (23.04.05 16:29) [22]:
>Кажется я понял что имеется ввиду (про отсутствие объекта).
Я не знаю, что Вы там поняли, но намекну, что COM-объекты могут быть реализованы на языке, не поддерживающем ООП в принципе.

to Набережных С. ©   (23.04.05 16:48) [23]:
>IntfGetComponent ввели, я убежден, как заплатку, предназначив
>для чисто внутреннего использования.
IntfGetComponent введен именно для получения ссылки на компонент, реализующий интерфейс. Используется при сохранении в потоки published свойств интерфейсного типа. Я бы не сказал, что это заплатка, это скорее можно отнести к внутренним механизмам VCL.


 
Набережных С. ©   (2005-04-25 19:58) [25]


> vuk ©   (25.04.05 19:12) [24]

Насчет сохранения интерфейсных свойств - возможно. Я не в курсе этого момента, упустил, надо будет глянуть, спасибо. Однако я его встречал где-то в местах, не связанных с этим механизмом. Но если так - тем более заплата, для расширения функциональности без кардинальной переделки существующих механизмов. Не было такой возможности изначально заложено - вот и пришлось изворачиваться:)

> это скорее можно отнести к внутренним механизмам VCL.

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



Страницы: 1 вся ветка

Текущий архив: 2006.03.05;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.038 c
2-1140188665
KyRo
2006-02-17 18:04
2006.03.05
TStringList


15-1139408697
SPeller
2006-02-08 17:24
2006.03.05
Ты из приморья, если...


15-1139389168
seg
2006-02-08 11:59
2006.03.05
Когда же перестанут издеваться над автомобилистами?


15-1139461748
nbv
2006-02-09 08:09
2006.03.05
Loockup поля


15-1139816379
alexeis
2006-02-13 10:39
2006.03.05
отказ от IDE?