На этом шаге мы рассмотрим интерфейс IDispatch.
Библиотека типов может не создаваться при реализации COM-сервера. Например, используя ранние версии Delphi, можно было создать СОМ-сервер автоматизации, который не содержал библиотеку типов. Соответственно при разработке клиентского приложения среда разработки не может получить информацию о методах, реализованных на сервере, порядок их реализации и списки формальных параметров. Следовательно, нет возможности на этапе компиляции клиента связать вызываемые методы с виртуальной таблицей интерфейсов сервера, и все, что выше говорилось о вызове методов объектов, реализовать невозможно.
В COM-технологии предусмотрена возможность доступа к методам интерфейса при отсутствии информации о порядке реализации методов в виртуальной таблице. При реализации интерфейсов среда разработки может сохранить текстовые названия методов и запомнить их в файле, где находится скомпилированный код COM-сервера. Это означает, что в COM-сервере был реализован интерфейс IDispatch. Он имеет два основных метода: GetIDOfNames и Invoke. Клиент обычным путем получает ссылку на интерфейс IDispatch сервера и может вызвать его метод GetIDOfNames. В качестве параметра указывается текстовое название метода, которое интересует клиента. Если IDispatch находит на сервере метод с таким названием, то он возвращает его идентификатор - DispID. Далее клиентское приложение использует этот идентификатор и специальным образом упакованные переменные в качестве параметров другого метода IDispatch - Invoke. Сервер распаковывает этот список параметров и вызывает метод с данным DispID с полученным от клиента списком параметров.
Поскольку связь между вызываемыми методами устанавливается при выполнении приложения, то такой способ вызова методов интерфейсов называют поздним связыванием (Late Building). Соответственно для вызова методов, таким образом, требуется провести большее число операций, чем при прямом обращении к виртуальной таблице, и это может сказаться на скорости их выполнения. При отсутствии библиотеки типов на этапе разработки сервера невозможно проверить правильность написания имен методов и списков параметров методов. Это может обнаружиться только на этапе выполнения клиентского приложения, когда произойдет исключение. Поэтому клиентское приложение, использующее сервер с помощью интерфейса IDispatch, обязательно следует тестировать на предмет корректного выполнения всех команд.
При разработке и тестировании COM-сервера также лучше создать клиентское приложение, реализующее вызовы методов сервера через IDispatch. Это лучше сделать потому, что таблица виртуальных методов какого-либо интерфейса на сервере может модифицироваться при добавлении и/или удалении методов. При этом порядок их следования в таблице изменяется и необходимо заново импортировать библиотеку типов, что разработчик часто сделать забывает. В этом случае при запуске клиентского приложения, как правило, вскоре происходит крах стека, и при работе в среде Windows это может даже привести к краху операционной системы.
Кроме того, при наличии библиотеки типов, при реализации нотификационных сообщений в элементах управления ActiveX используется вызов нотификаций через интерфейс IDispatch, и только через него! Элемент управления ActiveX определяет интерфейс для поддержки нотификационных сообщений, но сам его не создает. Он обязан быть реализован на клиенте, а элемент управления ActiveX обязан получить ссылку на него и вызывать методы этого интерфейса в ответ на события, происходящие с ним. Поскольку СОМ-сервер обязан быть скомпилирован раньше клиента, нет никакой возможности на этапе компиляции сервера получить доступ к таблице виртуальных методов клиента и связать нотификационные сообщения с методами, определенными в клиенте.
Со следующего шага мы рассмотрим, что такое маршалинг и как происходит экспорт объектов через адресное пространство процесса.