Доступ к объекту автоматизации


Сервер автоматизации предоставляет своим клиентам для доступа объект специального типа — dispatch object. При этом в адресном пространстве приложения клиента, называемого в этом случае контроллером, присутствует вариантная переменная, содержащая интерфейс IDispatch, предоставляющий ему доступ к этому объекту на OLE-сервере.

Фактически у клиента имеется три варианта доступа к объектам:
• Используя интерфейс IDispatch (доступ не отличается от доступа к обычному СОМ-серверу. Вызов методов происходит через VMT).
pSum:=CoSum.Create; (с помощью библиотеки типов)
• Используя в качестве интерфейса диспинтерфейс (этот вариант похож на предыдущий).

pdSum:=CoSum.Create As ISumDisp;
pdSum:=ISumDisp(CoSum.Create);
pdSum:=CreateComObject(Class_Sum) As ISumDisp;

• Используя вариантную переменную (Variant), которая инициализируется функцией:

CreateOleObject(Const ProgID: String): IDispatch;

В этом случае доступ осуществляется по имени объекта — ProgID. Считается, что этот вариант вызова более медленный, чем через виртуальную таблицу.

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

Фактически, вызывающий метод диспинтерфейса клиент, сам выполняет своеобразный маршалинг и демаршалинг. Перед вызовом метода Invoke, он должен упаковать параметры диспинтерфейса в вариант (variant).

Фактически для любого метода, вызываемого через переменную типа Variant, происходит следующее:
• Приложение Delphi передает имя метода объекта на сервере методу интерфейса IDispatch.GetDsOfName.
• Метод интерфейса IDispatch.GetDsOfName возвращает DispID, который однозначно соответствует имени метода объекта сервера.
• Приложение Delphi вызывает метод Invoke, используя DispID.

Для обращения к объектам Automation в Delphi используется тип Ole Variant — запись TVarData с четырьмя фиксированными и 16 вариантными полями. Когда OleVariant ссылается на объект Automation, можно вызвать как методы объекта, так и методы доступа разделов Read или Write свойства. Чтобы это сделать, необходимо включить модуль ComObj в секцию Uses одного из модулей, программы или библиотеки.

Массивы Variant с элементами типа varByte — привилегированный метод пересылки двоичных данных между контроллерами Automation и серверами. Такие массивы не подчинены никакой трансляции их данных и могут эффективно применяться, используя функции VarArrayLock и VarArrayUnlock. С их помощью можно обеспечить маршалинг произвольных структур данных.

Вызов методов объекта Automation происходит во время выполнения программы и не требует никаких предыдущих объявлений метода. Проверка правильности этих обращений во время компиляции программы не проводится.

Методика создания контролера автоматизации

Программы-клиенты для доступа к объектам автоматизации обычно называют контроллерами автоматизации.

Для создания контроллера автоматизации следует:
а) Создать проект и включить, например, в класс TForm1 переменные:

Туре
TForm1=Class(TForm)
Public
vSum: Variant; //Для доступа по имени программы
pSum: ISum; // Для доступа через интерфейс
pdSum: ISumDisp; // Для доступа через диспинтерфеис
End;

б) В число блоков экранной формы следует включить блок с описанием интерфейсов, поместив в рабочий каталог файл библиотеки типов сервера.
Uses OLEXE_TLB;

в) Далее следует обеспечить доступ к объекту одним из следующих способов:

vSum:=CreateOleObject(‘OLEXE.Sum’);
pSum:=CoSum.Create;
pdSum:=CoSum.Create As ISumDisp;
// Можно и иначе:
pdSum:=ISumDisp(CoSum.Create);
pdSum:=CreateComObject(Class_Sum) As ISumDisp;

Любой из указанных вызовов приведет к загрузке сервера и созданию объекта. После этого можно обращаться к методам и свойствам объекта.

Следует иметь в виду, что использование интерфейсов всегда более производительно, чем использование диспинтерфейсов и, тем более, переменных типа Variant (OleVariant), поскольку они используют позднее связывание.

Двойной (dual) интерфейс — интерфейс, поддерживающий связывание времени компиляции (раннее связывание с помощью интерфейсов) и связывание времени выполнения (позднее связывание с помощью переменной типа Variant). Двойные интерфейсы наследуются от IDispatch. В dual интерфейсах VMT увеличивается за счет включения прямых указателей на методы диспинтерфейса. Поэтому возможен доступ и через метод Invoke и напрямую.

Все методы двойного интерфейса должен использовать safecall соглашение, и все параметры метода и тип результата должны быть типа: Byte, Integer, Smalllnt, Currency, Real, Double, Real48, Single, AnsiString, ShortString, TDateTime, Variant, OleVariant и WordBool.

Серверы автоматизации, создаваемые в Delphi, автоматически поддерживают дуальность.


Комментарии запрещены.




Статистика