Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конспект лекций РСОИ.doc
Скачиваний:
20
Добавлен:
04.11.2018
Размер:
1.93 Mб
Скачать

2.8.3. Створення клієнта автоматизації

Розглянемо приклад створення клієнта автоматизації для сервера UnitSrv.dll. Інтерфейс із користувачем реалізується за допомогою шести кнопок. Призначення трьох лівих кнопок - створення екземпляра сервера і реалізації доступу до нього клієнта одним із трьох можливих способів — за допомогою звичайного інтерфейсу, через змінні типу variant і за допомогою інтерфейсу диспетчирування. Кнопки праворуч виконують ті самі функції, що й аналогічні кнопки ліворуч, але кожна процедура повторюється 100 000 разів, щоб можна було зафіксувати час виконання (рис. 2.6).

Програмний код, що організує доступ до сервера, досить простий у всіх трьох варіантах. Спочатку розглянемо, як реалізується доступ до сервера через звичайний інтерфейс.

procedure TFormCli.btnInterfaceClick(Sender: TObject);

var

I: IAreaUnitConverter;

begin

I := CoAreaUnitConverter.Create;

ShowMessage(FloatToStr(I.Convert(1.0, 0, 1)));

end;

Викликання функції CoAreaUnitConverter.Create створює екземпляр сервера автоматизації, а викликання методу I.Convert перераховує 1 квадратний метр у квадратні сантиметри. Врахуйте, що в результаті роботи механізму підрахунку посилань екземпляр застосунка-сервера буде автоматично закритий наприкінці виконання процедури.

Тепер розглянемо, як реалізується доступ до того ж самого сервера через змінні типу variant.

procedure TFormCli.btnVariantClick(Sender: TObj ect);

var

V: Variant;

begin

V := CreateOleObject{'UnitSrv.AreaUnitConverter');

ShowMessage(FloatToStr(V.Convert(1.0, 0, 1)));

end;

У цьому фрагменті програмного коду багато відмінностей від попереднього. У першому рядку викликається функція CreateOleObject для створення екземпляра сервера. При звертанні до функції CreateOleObject як ім'я класу треба передати параметр "UnitSrv.AreaUnitConverter". Середовище Delphi самостійно формує цей рядок, виконуючи конкатенацію імені сервера, символу "крапка" й імені сполученого класу. Щоб переконатися в цьому, гляньте на інформацію про бібліотеку типів UnitSrv.tlb.

У вікні Type Library Editor видно, що ім'я бібліотеки UnitSrv, а сполучений клас, виділений у списку об'єктів, названий AreaUnitConverter. Отже, ім'я класу для об’єкту — це UnitSrv.AreaUnitConverter.

Є й інший метод для визначення імені класу сервера. Потрібно заглянути в перелік GUID у системному реєстрі Windows.

Ці методи не можна використовувати в тому випадку, якщо ви використовуєте сервер, створений де-небудь в іншому місці, причому зовсім не обов'язково в середовищі Delphi, або якщо не відомий GUID необхідного об'єкту. У таких випадках слід звернутися до документації на сервер і знайти в ній імена класів, необхідні для розроблення застосунків-клієнтів.

Після того як функція CreateOleObject запише посилання на сервер автоматизації в змінну V типу variant, до сервера можна звертатися так само, як до інтерфейсу. Але внутрішній механізм виконання викликів через змінну типу variant значно відрізняється від того, що використовується до інтерфейсів, та й працює він значно повільніше.

Останній метод одержання доступу до сервера грунтується на використанні інтерфейсу диспетчирування.

procedure TFormCli.btnDispInterfaceClick(Sender: TObject);

var

DI: IAreaUnitConverterDisp;

begin

DI := CoAreaUnitConverter.Create as IAreaUnitConverterDisp;

ShowMessage(FloatToStr(DI.Convert(1.0, 0, 1)));

end;

Цей фрагмент програмного коду практично ідентичний тому, який використано під час обговорення першого методу з використанням звичайного інтерфейсу. Єдина відмінність полягає в тому, що інтерфейс, отриманий при викликанні CoAreaUnitConverter.Create, приводиться до типу інтерфейсу диспетчирування IAreaUnitConverterDisp.

Текст програми головного модуля застосунка-клієнта UnitCli (застосунок UnitCli, файл MainForm.pas):

unit MainForm;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type

TFormCli = class(TForm)

btnVariant: TButton;

btnInterface: TButton;

btnDispInterface: TButton;

btnTimeInterface: TButton;

btnTimeVariant: TButton;

btnTimeDispInterface: TButton;

lblInterface: TLabel;

lblVariant: TLabel;

lblDisplnterface: TLabel;

procedure btnVariantClick(Sender: TObject);

procedure btnInterfaceClick(Sender: TObject);

procedure btnDispInterfaceClick(Sender: TObject);

procedure btnTimeInterfaceClick(Sender: TObject);

procedure btnTimeVariantClick(Sender: TObject);

procedure btnTimeDispInterfaceClick(Sender: TObject);

private

{ Оголошення закритих членів}

public

{ Оголошення загальнодоступних членів }

end;

var

FormCli: TFormCli;

Implementation

uses ComObj, UnitSrv_TLB;

{$R *.DFM}

procedure TFormCli.btnVariantClick(Sender: TObject);

var

V: Variant;

begin

V := CreateOleObject('UnitSrv.AreaUnitConverter');

ShowMessage(FloatToStr(V.Convert(1.0, 0, 1)));

end;

procedure TFormCli.btnInterfaceClick(Sender: TObject);

var

I: IAreaUnitConverter;

begin

I := CoAreaUnitConverter.Create;

ShowMessage(FloatToStr(I.Convert(1.0, 0, 1)));

end;

procedure TFormCli.btnDispInterfaceClick (Sender: TObject);

var

DI: IAreaUnitConverterDisp;

begin

DI := CoAreaUnitConverter.Create as IAreaUnitConverterDisp;

ShowMessage(FloatToStr(DI.Convert(1.0, 0, 1)));

end;

procedure TFormCli.btnTimeInterfaceClick(Sender: TObject);

var

I: IAreaUnitConverter;

Count: Integer;

Dbl: Double;

T1, T2: DWord;

begin

I := CoAreaUnitConverter.Create;

T1 := GetTickCount;

for Count := 1 to 100000 do Dbl:=I.Convert(1.0, 0, 1);

T2:=GetTickCount;

lblInterface.Caption:=IntToStr(T2-T1) + ‘ms’;

end;

procedure TFormCli.btnTimeVariantClick(Sender: TObject);

var

V: Variant;

Count: Integer;

Dbl: Double;

T1, T2: DWord;

begin

V := CreateOleObject('UnitSrv.AreaUnitConverter');

T1 := GetTickCount;

for Count := 1 to 100000 do Dbl := V.Convert(1.0, 0, 1);

T2 := GetTickCount;

lblVariant. Caption := IntToStr(T2 – T1) + ' ms';

end;

procedure TFormCli.btnTimeDispInterfaceClick(Sender:TObject);

var

DI: IAreaUnitConverterDisp;

Count: integer;

Dbl: Double;

T1, T2: DWord;

begin

DI := CoAreaUnitConverter. Create as IAreaUnitConverterDisp;

T1 := GetTickCount;

for Count := 1 to 100000 do Dbl := DI. Convert (1.0, 0, 1);

T2 := GetTickCount;

lblDispInterface.Caption := IntToStr(T2 - Tl) + ' ms';

end;

end.

Цей застосунок може організувати доступ до сервера одним із трьох способів: за допомогою звичайного інтерфейсу, через змінні типу variant і за допомогою інтерфейсу диспетчирування. На практиці в застосунку-клієнті використовується один із цих способів.

Мета застосування в одному застосунку відразу трьох різних способів полягає в наступному:

  • бажано продемонструвати, як організувати в програмі кожний з них;

  • надання можливості порівняти динамічні характеристики кожного з цих способів.

Зверніть увагу на показники часу виконання. Продемонстровані значення свідчать, що найшвидший спосіб звертання до сервера автоматизації — за допомогою звичайного інтерфейсу. Звертання через змінні типу variant майже на порядок повільніше, а проміжну позицію займає звертання за допомогою інтерфейсів диспетчирування.

Якщо ви уважно ознайомилися з поданим матеріалом, то тепер маєте досить чітке уявлення про вбудований сервер автоматизації. Але на жаль, вбудовані сервери автоматизації можна використовувати далеко не завжди. Якщо бажано мати сервер автоматизації, що працював би в адресному просторі, відмінному від адресного простору застосунка-клієнта, то знадобиться розробити зовнішній сервер автоматизації.

Контрольні запитання та завдання:

  1. Для чого використовується клас TAutoObject?

  2. Опишіть три методи створення об’єкту автоматизації.

  3. Опишіть методику створення клієнт-серверної системи на основі внутрішнього сервера автоматизації.