Реализация событий COM+ в среде Delphi 5Источник: delphikingdom Андрей Семак
Автор: Андрей Семак, Королевство Delphi Введение Обработка событий является одним из ключевых моментов в COM. Существует масса программ, для нормального функционирования которых требуется поддержка событий.GUI пользователя должен уметь обрабатывать различное количество событий, например, таких как: нажатие на кнопку мыши, перемещение мыши по экрану и т.д. Приблизительно так же может возникнуть потребность обрабатывать события внутри объектов COM. В данной статье мы рассмотрим принцип работы свободно связанных событий и создадим наглядное приложение для демонстрации использования такого типа событий в COM+. (Для более детальной информации о события в COM+ смотрите статью А.Новика "Система поддержки событий COM+" на сайте журнала "Клиент-Сервер").
До появления COM+, модель COM поддерживала систему событий, реализованную через интерфейс IConnectionPointContainer. Это жестко связанные события. (В данной статье, мы не будем рассматривать реализацию этого подхода). В COM+ появилось новое понятие: СВОБОДНО СВЯЗАННЫЕ СОБЫТИЯ (Loosely coupled events - LCE), разработанные для удовлетворения потребностей распределенных вычислений. В COM+ Инициатор события (Издатель) и потребитель (Подписчик) свободно связаны.Информация от различных издателей хранится в каталоге COM+, а подписчики указывают, какую информацию они хотят получать, регистрируясь в каталоге.
Для реализации свободно связанных событий вы должны создать компонент EventClass, который будет зарегистрирован в каталоге COM+. Подписчики вызываются объектом события, который определяет и активизирует объекты, подписанные на него. Следует различать виды подписки. Существует временная и постоянная подписки. Временная подписка (transient) создается средствами административного API. Для более детальной информации можно обратиться в MSDN. Управлять жизненным циклом такой подписки нужно программными средствами. А не средствами ComponentServices. Постоянная подписка (persistent) создается средствами ComponentServices. Такая подписка в состоянии пережить перезапуск системы.Фильтрация существует только в системе COM+. Такой возможности нет в системе жестко связанных событий. Её суть мы рассмотрим дальше, при более детальном изучении примера.
Допустим, у нас существует задача на базе существующей системы, функционирующей в среде COM+, реализовать систему ведения собственно журнала событий в текстовом файле. Для начала нам нужно реализовать компонент EventClass, о котором речь шла выше. Он будет представлять собой пустую заглушку для подписчика. Именно через него будут запускаться наши подписчики в каталоге COM+. Когда компонент-издатель будет создавать событие, компонент EventClass передаст все входящие параметры события и активизирует всех подписчиков.
type LogMessageTypes = TOleEnum; const lmtInformation = $00000000; lmtWarning = $00000001; lmtError = $00000002; lmtFatal = $00000003; lmtDebug = $00000004; lmtUnknown = $00000005; type TSysLogEvent = class(TAutoObject, ISysLogEvent) protected procedure ReportLog(enMsgType: LogMessageTypes; const strUserName, strModuleName, strMsgText: WideString); safecall; { Protected declarations } end;Библиотека типов изображена на рис. 1. В разделе Implementation создадим заглушку метода для EventClass: implementation uses ComServ; procedure TSysLogEvent.ReportLog(enMsgType: LogMessageTypes; const strUserName, strModuleName, strMsgText: WideString); begin // Event class methods are not implemented. end; initialization TAutoObjectFactory.Create(ComServer, TSysLogEvent, Class_SysLogEvent, ciMultiInstance, tmApartment); end.На этом закончим. Остается зарегистрировать заглушку в нашем приложении COM+. Если приложение не создано, создайте его через средства ComponentServices. Окно регистрация компонента EventClass изображено на рис.2.
После регистрации компонента EventClass создадим компонент-подписчик.
unit SysLogUnit; interface uses ComObj, ActiveX, SystemLogger_TLB, StdVcl, LogEvent_TLB, Dialogs; type TSysLog = class(TAutoObject, ISysLog, ISysLogEvent) protected procedure ReportLog(enMsgType: LogMessageTypes; const strUserName, strModuleName, strMsgText: WideString); safecall; { Protected declarations } end; implementation uses ComServ, SysUtils; procedure TSysLog.ReportLog(enMsgType: LogMessageTypes; const strUserName, strModuleName, strMsgText: WideString); begin ShowMessage('MessageType : '+IntToStr(enMsgtype)+#10#13+ 'ModuleName : '+strModuleName+#10#13+ 'UserName : '+strUserName+#10#13+ 'TextMessage : '+strMsgText); end; initialization TAutoObjectFactory.Create(ComServer, TSysLog, Class_SysLog, ciMultiInstance, tmApartment); end.Зарегистрируйте компонент в каталоге COM+ и подпишите его к компоненту EventClass. Как это сделать? Смотрите рис. 4. Рис. 4 Рис. 5 Итак, у вас на компьютере установлены объекты EventClass и подписчик.
Создадим простенькое приложение и проверим существующею связку. Создайте бизнес-объект COM+ инициирующий в любом своем методе метод-событие ReportLog. unit BsObjectUnit; interface uses ComObj, ActiveX, BsObject_TLB, StdVcl, LogEvent_TLB; type TBusinessObject = class(TAutoObject, IBusinessObject) protected function NewObject(param1: Integer): HResult; safecall; { Protected declarations } end; implementation uses ComServ; function TBusinessObject.NewObject(param1: Integer): HResult; var LogEvent : ISysLogEvent; begin LogEvent := CoSysLogEvent.Create; try LogEvent.ReportLog(lmtInformation, 'Nonamed', 'BsObjectUnit','TBusinessObject.NewObject executed!') except LogEvent.ReportLog(lmtInformation, 'Nonamed', 'BsObjectUnit','TBusinessObject.NewObject failed!') end; end; initialization TAutoObjectFactory.Create(ComServer, TBusinessObject, Class_BusinessObject, ciMultiInstance, tmApartment); end. После вызова метода NewObject у объекта BusinessObject будет создано событие, которое создаст объект SysLog и запишет и отобразит информацию в диалоговом окне. Подписчиков у созданного объекта EventClass может быть неограниченное количество с самыми разнообразными функциями, от отображения диалогового окна до записи данных в отдельную БД.
Механизм фильтрации подписчиков использует строку условия фильтрации, являющуюся свойством подписки. Такая фильтрация выполняется для каждого метода и каждой подписки. Вы можете использовать строку, используя имена параметров из библиотеки типов. Можно использовать так же стандартные операции отношения, вложенные скобки и ключевые слова AND, OR, NOT. Строка может быть определена с помощью средств ComponentServices или средств административного API. |