Добавить в цитаты Настройки чтения

Страница 207 из 372

• PerUser

Это вариант постоянной подписки, который можно использовать только в том случае, когда издатель и подписчик работают на одном компьютере. В записи о подписке этого типа хранится SID некоторого пользователя, в процессе которого был создан объект-подписчик. Подписка включается подсистемой событий только при входе пользователя с данным SID в систему и отключается при его выходе из системы.

Как и в случае регистрации событийного класса, зарегистрировать подписку может только администратор, используя программирование и/или Component Services. Каждая подписка на некоторое событие является объектом, хранимым в подсистеме событий. Подписаться можно на событийный интерфейс в целом (на все его методы) или на некоторый метод событийного интерфейса. Если необходимо подписаться на несколько методов событийного интерфейса (но не на все), нужно отдельно оформить подписку для каждого метода. Заметим, что подписчик должен реализовать все методы событийного интерфейса.

Начнем с программной регистрации подписки:

• Прежде всего формируется экземпляр реализованного в системе класса с идентификатором CLSID_CEventSubscription (объект подписки) и запрашивается указатель на интерфейс IEventSubscription этого класса.

• Интерфейс IEventSubscription используется для задания свойств объекта подписки:

♦ GUID регистрируемой подписки задается вызовом метода IEventSubscription:: put_SubscriptioniD (), где параметром является BSTR строка, задающая GUID подписки. Этот идентификатор должен быть уникален в данном сервисе событий,

♦ Имя регистрируемой подписки задается вызовом метода IEventSubscription:: put_SubscriptionName (), где параметром является BSTR строка, задающая название подписки. Это читаемая строка, предназначенная для администраторов,

♦ Уникальный идентификатор издателя задается вызовом метода IEventSubscription:: put_Publisherid (), где параметром является BSTR строка, задающая GUID издателя. Если эта информация не задана, то подписчик будет получать уведомления вне зависимости от того, какой издатель инициировал рассылку уведомлений через данный событийный класс,

♦ CLSID событийного класса задается вызовом метода IEventsSbscription:: put_EventClassiD (), где параметром является BSTR строка, задающая CLSID событийного класса, для получения уведомлений от которого и регистрируется данная подписка.

♦ Идентификатор событийного интерфейса, на который регистрируется подписка (а событийный класс может реализовывать несколько событийных интерфейсов) задается вызовом метода IEventsSbscription::putInterfaceiD, параметр типа BSTR задает GUID этого интерфейса.

♦ Метод iEventSubscription::putMethodName вызывается для задания метода событийного интерфейса, на который регистрируется подписка. Параметром является BSTR строка, задающая название метода,

♦ Вызов метода IEventSubscription::putSubscriberCLSID с параметром типа BSTR строка, задающим CLSID подписчика, используется в случае постоянной подписки. Данный CLSID будет использоваться подсистемой подписки для активации подписчика,

♦ Вызов метода IEventSubscription::putMashineName позволяет В виде BSTR строки задать имя машины, на которой следует в случае постоянной подписки активировать подписчика,

♦ Вызов метода IEventSubscription::putSubscriberInterfасе используется для организации временной подписки. В качестве параметра передается маршалированный указатель (типа IUnknown*) на интерфейс уже активированного подписчика, на который следует посылать уведомления,

♦ Вызов метода IEventВubscription::putPerUser позволяет задать подписку третьего типа, когда подписка действует только при входе в систему определенного пользователя — владельца подписки. Этот вариант используется только в том случае, когда подписчик активируется на на той же машине, где зарегистрирован событийный класс. Параметр типа BOOL включает или выключает это ограничение на подписку,

♦ Задать владельца подписки можно вызывая метод iEventSuscription::putOwnerSID, параметр типа BSTR задает Security ID владельца подписки.





• Формируется экземпляр реализованного в системе класса с идентификатором CLSID_CEventSystem и запрашивается указатель на его интерфейс IEventSystem.

• Вызывается метод Store этого интерфейса, которому в качестве первого параметра передается PROGID_EventSubscription, что указывает на то, что сохраняется именно объект-подписка, а в качестве второго параметра передается указатель на интерфейс IEventClass экземпляра класса с идентификатором CLSID_CEventSubscription, параметры которого настроены на регистрируемую подписку.

Фильтр на стороне издателя

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

Выше, при обсуждении свойств событийного класса упоминалось, что свойству MuitiInterfacePubiisherFilterCLSID можно программным путем присвоить CLSID некоторого класса, который будет рассматриваться подсистемой событий как фильтр, который на стороне издателя будет перехватывать рассылку уведомлений подписчикам.

При использовании данного подхода (а есть еще один, не обеспечивающий работу с асинхронными событийным классом и подписчиками и здесь не рассматриваемый) издательский фильтр должен реализовывать интерфейс IMultiInterfacePublisherFilter с двумя методами:

• Initialize

Когда издатель инициирует активацию экземпляра событийного класса, подсистема событий автоматически активирует издательский фильтр (если свойство MuitiInterfacePublisherFilterCLSID было задано). В случае какой-либо ошибки при активации фильтра не будет активирован и событийный объект. После активации фильтра подсистема событий сразу же вызывает метод initialize, которому в качестве единственного параметра (входного) передается указатель на реализованный в системе интерфейс IMuitiInterfaceEventControl. Через этот интерфейс фильтр может получить доступ к коллекции подписчиков на произвольный событийный интерфейс и метод в событийном классе, для которого и подготовлен данный фильтр. Достаточно вызвать метод IMuitiInterfaceEventControi::GetSubscriptions, среди параметров которого:

♦ [in] Идентификатор событийного интерфейса.

♦ [in] Метод событийного интерфейса. Если название метода не существенно, то значение параметра NULL,

 [in] Критерий отбора объектов-подписок для включения в коллекцию подписок. Здесь задается BSTR сторка, представляющая логическое выражение, в которое входят свойства подписки, операторы отношения, константы, логические операторы и скобки. Если параметр равен NULL, то используется некоторый критерий отбора по умолчанию,

♦ [out] Указатель на IEventObjectCollection. Через этот интерфейс фильтр получает доступ к коллекции отобранных объектов-подписок и может в дальнейшем определять порядок их оповещения.

Заметим, что построенная при вызове IMuitiInterfaceEventControl::GetSubscriptions коллекция автоматически обновляется при добавлении/удалении подписок на данный событийный интерфейс (метод) в подсистеме событий.

 PrepareToFire

Данный метод собственно и осуществляет перехват процесса рассылки уведомлений. Как только издатель вызывает некоторый метод событийного интерфейса, инициируя тем самым рассылку уведомлений подписчикам, подсистема событий вместо обычного процесса рассылки уведомлений всем подписчикам в некотором заранее неопределенном порядке, вызывает метод PrepareToFire, предоставляя фильтру возможность определить кому и в каком порядке следует послать уведомление. Отбор подписчиков проводится из коллекции подписок, построенной при инициализации фильтра. Вот параметры этого метода: