Реализация событий COM+ в среде Delphi 5
Андрей Семак. Компания ProFIX, май 2001г.
Введение
Обработка событий является одним из ключевых моментов в COM. Существует масса программ, для нормального функционирования которых требуется поддержка событий. GUI пользователя должен уметь обрабатывать различное количество событий, например, таких как: нажатие на кнопку мыши, перемещение мыши по экрану и т.д. Приблизительно так же может возникнуть потребность обрабатывать события внутри объектов COM. В данной статье мы рассмотрим принцип работы свободно связанных событий и создадим наглядное приложение для демонстрации использования такого типа событий в COM+. (Для более детальной информации о события в COM+ смотрите статью А.Новика «Система поддержки событий COM+» на сайте журнала «Клиент-Сервер»).Что такое свободно связанные события? Понятие «Издатель-Подписчик»
До появления COM+, модель COM поддерживала систему событий, реализованную через интерфейс IConnectionPointContainer. Это жестко связанные события. (В данной статье, мы не будем рассматривать реализацию этого подхода). В COM+ появилось новое понятие: СВОБОДНО СВЯЗАННЫЕ СОБЫТИЯ (Loosely coupled events - LCE), разработанные для удовлетворения потребностей распределенных вычислений. В COM+ Инициатор события (Издатель) и потребитель (Подписчик) свободно связаны. Информация от различных издателей хранится в каталоге COM+, а подписчики указывают, какую информацию они хотят получать, регистрируясь в каталоге.Архитектура событий в COM+
Для реализации свободно связанных событий вы должны создать компонент EventClass, который будет зарегистрирован в каталоге COM+. Подписчики вызываются объектом события, который определяет и активизирует объекты, подписанные на него. Следует различать виды подписки. Существует временная и постоянная подписки. Временная подписка (transient) создается средствами административного API. Для более детальной информации можно обратиться в MSDN. Управлять жизненным циклом такой подписки нужно программными средствами. А не средствами ComponentServices. Постоянная подписка (persistent) создается средствами ComponentServices. Такая подписка в состоянии пережить перезапуск системы. Фильтрация существует только в системе COM+. Такой возможности нет в системе жестко связанных событий. Её суть мы рассмотрим дальше, при более детальном изучении примера.Пример реализации компонента EventClass
Допустим, у нас существует задача на базе существующей системы, функционирующей в среде COM+, реализовать систему ведения собственно журнала событий в текстовом файле. Для начала нам нужно реализовать компонент EventClass, о котором речь шла выше. Он будет представлять собой пустую заглушку для подписчика. Именно через него будут запускаться наши подписчики в каталоге COM+. Когда компонент-издатель будет создавать событие, компонент EventClass передаст все входящие параметры события и активизирует всех подписчиков.Важно! Метод события может содержать только входные параметры [in]. Выходным может быть только результирующий тип HRESULT, принятый в COM для определения статуса завершения S_OK, в результате удачи или E_FAIL, в результате неудачи выполнения метода.
Запустим среду Delphi, создадим простую ActiveX библиотеку и поместим в неё объект автоматизации (Automation Object). Определим нумератор типов ошибок и создадим интерфейс ISysLogEvent с методом ReportLog.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.

Рис. 1
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.

Рис. 2
Пример реализации Объекта-подписчика
После регистрации компонента EventClass создадим компонент-подписчик.Точно так же, как при создании компонента EventClass создадим библиотеку и объект автоматизации. Немного будет отличаться наполнение реализации методов и метод регистрации.
Создадим интерфейс с методом, аналогичным методу интерфейса ILogEvent – ISysLog (Рис. 3):

Рис. 3
Важно! Не забудьте подключить в вашу библиотеку типов зарегистрированную в ComponentServices библиотеку с заглушкой EventClass и укажите интерфейс ISysLogEvent в разделе Implements как показано на рис. 3а.

Рис. 3a
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
Пример реализации методов издателя
Создадим простенькое приложение и проверим существующею связку. Создайте бизнес-объект 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.Архив с примерами (20.5K)
| 2011 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2010 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2009 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2008 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2007 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2006 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2005 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2004 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2003 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2002 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2001 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2000 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 1999 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
Последние статьи
- Услуги аутсорсинга в области программирования
- Как продлить срок службы картриджей
- Мошенничество во Всемирной Паутине. Осторожно: фишинг!
- Web-студия
- Как легально поднять уровень индекса цитирования.
- Мы реально сможем помочь вам в управлении предприятием
- Создание сайтов – популяризация вашего замысла
- Свой сайт. Управление ресурсом
- Семантическое ядро сайта или правила подбора ключевых фраз
- Инфо-Предприятие: выгоды явные и не явные
Литература
- Программирование в среде Delphi 8 for .NET
- Практикум по Delphi для решения прикладных задач
- Фундаментальные алгоритмы и структуры данных в Delphi
- Delphi 6. Программирование на Object Pascal
- Delphi и технология COM
- Delphi в шутку и всерьез: что умеют хакеры
- Программирование в Delphi глазами хакера
- Delphi 2005. Секреты программирования
- Искусство создания компонентов Delphi
- Приемы программирования в Delphi на основе VCL
- Программирование баз данных в Delphi 7
- Программирование баз данных в Delphi
- Программирование в среде Delphi
- Программирование в Delphi 7
- Язык SQL в Delphi 5