Delphi и COM


         

События в COM


При возникновении события в COM-сервере, которое он должен передать клиенту, сервер должен вызвать какой-либо из методов клиента. Фактически в этот момент клиент с сервером меняются местами. Обращение к клиенту осуществляется при помощи стандартных механизмов COM. Основная идея заключается в том, что сервер, генерирующий события, декларирует интерфейс их обработчика. Клиент, подписывающийся на события, должен реализовать этот интерфейс (то есть фактически должен включать в себя COM-объект, реализующий интерфейс). Кроме того, сервер должен  реализовать стандартные интерфейсы COM, позволяющие зарегистрировать на нем обработчик событий. Используя эти интерфейсы, клиент регистрирует на сервере интерфейс обработчика событий, позволяя серверу вызывать свои методы. Рассмотрим основные интерфейсы, используемые в этом процессе.

type   IConnectionPointContainer = interface     ['{B196B284-BAB4-101A-B69C-00AA00341D07}']     function EnumConnectionPoints(out Enum: IEnumConnectionPoints): HResult;       stdcall;     function FindConnectionPoint(const iid: TIID;       out cp: IConnectionPoint): HResult; stdcall;   end;

Этот интерфейс должен реализовываться каждым COM-объектом, который позволяет подключаться к своим событиям. Ключевой метод FindConnectionPoint  получает GUID интерфейса-обработчика и возвращает указатель на соответствующую этому обработчику «точку подключения». Такой подход дает возможность серверу иметь несколько интерфейсов для обработки событий, а клиентам подключаться к ним по мере необходимости. В случае успеха метод возвращает S_OK, в случае неудачи — код ошибки.

Точка подключения также представляет собой интерфейс:

type   IConnectionPoint = interface     ['{B196B286-BAB4-101A-B69C-00AA00341D07}']     function GetConnectionInterface(out iid: TIID): HResult; stdcall;     function GetConnectionPointContainer(out cpc: IConnectionPointContainer):       HResult; stdcall;     function Advise(const unkSink: IUnknown; out dwCookie: Longint): HResult;       stdcall;     function Unadvise(dwCookie: Longint): HResult; stdcall;     function EnumConnections(out Enum: IEnumConnections): HResult; stdcall;   end;

Ключевые методы этого интерфейса — Advise и Unadvise.

function Advise(const unkSink: IUnknown; out dwCookie: Longint): HResult;   stdcall;

Этот метод регистрирует на сервере клиентский интерфейс обработчика событий, который передается в параметре unkSink. Метод возвращает dwCookie — идентификатор подключения, который должен использоваться при отключении обработчика событий. Начиная с этого момента сервер при возникновении события вызывает методы переданного ему интерфейса-обработчика.

function Unadvise(dwCookie: Longint): HResult; stdcall;

Метод Unadvise отключает обработчик от сервера. Теперь, когда мы имеем представление, как COM реализует обработчики событий, можно продолжить работу над нашим сервером.



Содержание раздела