На этом шаге мы рассмотрим способы связывания сервера и контроллера.
В рассмотренном на предыдущем шаге контроллере использовалось так называемое
позднее связывание (late binding). В этом случае анализ существования методов и свойств объекта автоматизации
не производится до момента обращения к ним на этапе выполнения. Поэтому при создании контроллера, ориентированного на позднее связывание,
высока вероятность внесения незамеченных ошибок в названия методов и свойств.
Контроллер автоматизации может быть создан и иным способом - путем импорта библиотеки типов. В этом случае в адресном
пространстве контроллера создается набор классов для управления сервером, обладающих теми же самыми методами, что и подлежащий автоматизации объект.
Это позволяет непосредственно обращаться к методам данных классов, а также выявлять на этапе компиляции ошибки в названиях методов сервера.
Чтобы иметь возможность создать такой контроллер, следует в меню Delphi выбрать команду Project | Import Type Library.... Откроется диалоговое
окно импорта библиотеки типов (рисунок 1).
Рис.1. Импорт библиотеки типов сервера
В списке этого окна необходимо выбрать импортируемый сервер. Строка названия сервера соответствует значению в поле Help String окна редактора
библиотеки типов для интерфейса AutoServ: ITypeLibrary. Обязательно требуется снять флажок
Generate Component Wrapper (о нем будет сказано ниже). Для подтверждения выбора следует щелкнуть на кнопке Create Unit (по не Install).
В результате будет создан файл с расширением *.pas в каталоге Delphi6\Imports. Этот файл следует включить в проект контроллера, чтобы сделать доступными
описания классов для управления сервером (Delphi делает это автоматически).
В этом случае код контроллера можно создать двумя способами. Один их этих способов реализует так называемое раннее связывание (early binding)
клиента с сервером, то есть создание и использование в клиентском приложении таблицы виртуальных методов, полностью аналогичной таблице виртуальных методов
сервера. Для этого в секции uses модуля реализации клиента нужно сослаться на импортированный модуль AutoServ_TLB. В модуле AutoServ_TLB
объявляется класс ITest; а переменную FServ этого типа нужно объявить в секции private класса TForm1. Пример реализации методов контроллера
автоматизации, созданного с применением раннего связывания, приведен ниже.
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, AutoServ_TLB; type TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Button5: TButton; Button6: TButton; Button7: TButton; Button8: TButton; Button9: TButton; Button10: TButton; Edit1: TEdit; CheckBox1: TCheckBox; OpenDialog1: TOpenDialog; SaveDialog1: TSaveDialog; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button7Click(Sender: TObject); procedure Button8Click(Sender: TObject); procedure CheckBox1Click(Sender: TObject); procedure Button5Click(Sender: TObject); procedure Button6Click(Sender: TObject); procedure Button9Click(Sender: TObject); procedure Button10Click(Sender: TObject); private { Private declarations } FServ: ITest; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} //Подключение к серверу. procedure TForm1.Button1Click(Sender: TObject); begin FServ := CoTest.Create;; end; //Отключение от сервера. procedure TForm1.Button2Click(Sender: TObject); begin FServ := Nil; end; //Получить текст от сервера. procedure TForm1.Button4Click(Sender: TObject); begin if Assigned(FServ) then Memo1.Text := FServ.Text; end; //Отправить текст на сервер. procedure TForm1.Button3Click(Sender: TObject); begin if Assigned(FServ) then FServ.Text := Memo1.Text; end; //Получение ширины от сервера. procedure TForm1.Button7Click(Sender: TObject); begin if Assigned(FServ) then Edit1.Text := IntToStr(FServ.Width); end; //Задание ширины окна сервера. procedure TForm1.Button8Click(Sender: TObject); begin if Assigned(FServ) then FServ.Width := StrToInt(Edit1.Text); end; //Установить видимость/невидимость. procedure TForm1.CheckBox1Click(Sender: TObject); begin if Assigned(FServ) then FServ.Visible := CheckBox1.Checked; end; //Открыть файл на сервере. procedure TForm1.Button5Click(Sender: TObject); begin if Assigned(FServ) then if OpenDialog1.Execute then FServ.OpenFile(OpenDialog1.FileName); end; //Сохранить файл на севере. procedure TForm1.Button6Click(Sender: TObject); begin if Assigned(FServ) then if SaveDialog1.Execute then FServ.SaveFile(SaveDialog1.FileName); end; //Создать новый файл на сервере. procedure TForm1.Button9Click(Sender: TObject); begin if Assigned(FServ) then FServ.NewFile; end; //Добавить строку на сервер. procedure TForm1.Button10Click(Sender: TObject); begin if Assigned(FServ) then FServ.AddLine(Edit1.Text); end; end.
Текст этого приложения можно взять случае с классами. При использовании же его с
интерфейсами Delphi вызывает метод <ссылка на интерфейс>.Query Interface с GUID для интерфейса
<имя интерфейса>.
Хотелось бы обратить внимание на следующее. Хотя мы и смогли протестировать свойства и методы сервера автоматизации с
помощью созданного контроллера, у нас еще не было возможности произвести отладку той части кода, которая связана с
автоматизацией. Естественно, если клиент запускается иод управлением среды разработки Delphi, использовать тот
же самый экземпляр среды разработки для отладки сервера нельзя. Поэтому следует открыть проект сервера в отдельном
экземпляре среды разработки и запустить его на выполнение. Если после этого запустить приложение-контроллер (неважно,
под управлением другого экземпляра среды разработки или просто средствами операционной системы) и щелкнуть на кнопке
Подключиться, контроллер соединится с уже запущенным экземпляром сервера. Если в исходном тексте сервера
отмечены точки останова, при их достижении выполнение кода сервера прекращается и управление передается среде разработки.
Напомним, СОМ-сервер и СОМ-клиент могут быть написаны с использованием любых средств разработки,
поддерживающих СОМ-техпологию. Поэтому в принципе не возбраняется написать сервер автоматизации в Delphi,
а контроллер - в C++Builder или Visual Basic (или наоборот).
На следующем шаге мы рассмотрим коллекции объектов.