Скачиваний:
100
Добавлен:
01.05.2014
Размер:
1.56 Mб
Скачать

Раннее и позднее связывание

Рассмотренный выше пример создания контроллера использовал так называемое позднее связывание (late binding), или связывание на этапе выполнения. В этом случае, как было сказано выше, анализ существования методов и свойств объекта автоматизации не производится до момента обращения к ним на этапе выполнения. Поэтому при создании контроллера таким образом высока вероятность незамеченных ошибок в написании названий методов и свойств.

Контроллер автоматизации может быть создан и несколько другим способом - с помощью импорта библиотеки типов. В этом случае в адресном пространстве контроллера создается набор классов для управления сервером, обладающих теми же самыми методами, которыми обладает и подлежащий автоматизации объект. Это позволяет непосредственно обращаться к методам данных классов, а также выявить на этапе компиляции ошибки в названиях методов сервера.

Чтобы иметь возможность создать такой контроллер, следует из меню C++Builder выбрать опцию "Project/Import Type Library". В результате будут созданы файлы в подкаталоге Imports. Эти файлы следует включить в проект контроллера, чтобы сделать доступными описания классов для управления сервером (C++Builder делает это автоматически).

В этом случае код контроллера можно создать двумя способами. Один их этих способов реализует так называемое раннее связывание (early binding) клиента с сервером, то есть создание и использование в клиентском приложении таблицы виртуальных методов, полностью аналогичной таблице виртуальных методов сервера.

Пример кода контроллера автоматизации, реализующего раннее связывание, приведен ниже:

IMyAuto *serv;

void __fastcall TForm1::Button1Click(TObject *Sender)

{

serv = CoMyAuto::Create ();

}

void __fastcall TForm1::Button2Click(TObject *Sender)

{

serv = NULL;

}

void __fastcall TForm1::Button3Click(TObject *Sender)

{

if (serv)

{

Edit1->Text = IntToStr (serv->Width);

}

}

void __fastcall TForm1::Button4Click(TObject *Sender)

{

if (serv)

{

serv->Width = atoi (Edit1->Text.c_str ());

}

}

void __fastcall TForm1::Button8Click(TObject *Sender)

{

if (serv)

{

CheckBox1->Checked = serv->Visible;

}

}

void __fastcall TForm1::Button9Click(TObject *Sender)

{

if (serv)

{

serv->Visible = CheckBox1->Checked;

}

}

void __fastcall TForm1::Button5Click(TObject *Sender)

{

if (serv)

if (OpenDialog1->Execute ())

{

serv->OpenFile (WideString((OpenDialog1->FileName).c_str ()).c_bstr ());

}

}

void __fastcall TForm1::Button6Click(TObject *Sender)

{

if (serv)

if (SaveDialog1->Execute ())

{

serv->SaveFile (WideString((SaveDialog1->FileName).c_str ()).c_bstr ());

}

}

void __fastcall TForm1::Button7Click(TObject *Sender)

{

if (serv)

{

serv->NewFile ();

}

}

void __fastcall TForm1::Button10Click(TObject *Sender)

{

if (serv)

{

serv->AddLine (WideString((Edit1->Text).c_str ()).c_bstr ());

}

}

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

Есть еще и третий способ, основанный также на импорте библиотеки типов, но использующий позднее связывание:

IMyAuto3Disp V;

...

void __fastcall TForm1::Button1Click (TObject *Sender)

{

V = (IMyAuto3Disp) CreateOleObject ("Autoserv.MyAuto3");

}

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

Хотелось бы обратить внимание на то, что, хотя мы и смогли протестировать свойства и методы сервера автоматизации с помощью созданного контроллера, у нас еще не было возможности произвести отладку части кода, связанного с автоматизацией. Естественно, если клиент запускается под управлением среды разработки C++Builder, использовать тот же самый экземпляр среды разработки для отладки сервера невозможно. Поэтому следует открыть проект сервера в отдельном экземпляре среды разработки и запустить его на выполнение. Если после этого запустить приложение-контроллер (неважно, под управлением другого экземпляра среды разработки или просто средствами операционной системы) и нажать кнопку "Connect", контроллер соединится с уже запущенным экземпляром сервера. Если в исходном тексте сервера отмечены точки останова, при их достижении выполнение кода сервера прекращается и управление передается среде разработки.

Отметим один очевидный факт: СОМ-сервер и СОМ-клиент могут быть написаны с использованием любых средств разработки, поддерживающих СОМ-технологию. Поэтому в принципе не возбраняется написать сервер автоматизации с помощью Delphi, а контроллер - с помощью C++Builder (или наоборот).