Классы-заместители
Сервисная программа Wsdl .exe считывает описание Web-службы на языке WSDL и генерирует класс-заместитель, который формирует SOAP-запрос Web-службы. По умолчанию эта сервисная программа генерирует код класса-заместителя на языке С# [Можно выбрать CS, VB, JS или (в случае доступности) указать реализацию класса System::CodeDom::Compiler::CodeDomProvider (Система::CodeDom::Компилятор::CodeDomProvider) на любом языке.]. Язык C++ в данный момент она не поддерживает. Следовательно, в нашем примере класс-заместитель будет создан на С#. По умолчанию сервисная программа Wsdl .exe использует протокол SOAP [В конфигурационном файле можно указать также протоколы HttpGet, HttpPost или другой специальный протокол.]. В результате выполнения команды, приведенной ниже, будет сгенерирован класс-заместитель addproxy.cs на языке С#.
wsdl /out:addproxy.cs http://localhost/SimpleWebService/Add.asmx?WSDL
В файле addproxy.cs содержится исходный код класса-заместителя, в котором определен один конструктор и три метода. Конструктор устанавливает унифицированный указатель информационного ресурса (URL) данной Web-службы. Один из трех имеющихся методов реализует синхронный блокирующий вызов Web-службы. С помощью оставшихся двух методов реализован шаблон асинхронного вызова Web-службы, который обсуждался в главе 8 "Классы каркаса .NET Framework". Для асинхронного вызова Web-службы можно использовать методы BeginXXX и EndXXX созданного класса-заместителя [Очевидно, что в данном примере XXX = Add.]. Класс-заместитель имеет имя WebService, т.е. его имя совпадает с именем класса WebService.
Метод Invoke (Активизировать) класса SoapHttpClientProtocol формирует запросы, передаваемые по протоколу передачи гипертекстовых файлов HTTP, и обрабатывает ответы, получаемые по тому же протоколу. Сами же запросы и ответы содержатся в отсылаемых и получаемых SOAP-пакетах. Описанный выше пример класса-заместителя расположен в подкаталоге SimpleAddClient каталога SimpleWebService.
public class Test: System.Web.Services.Protocols.SoapHttpClientProtocol // общедоступный класс Испытание: // Система.Сеть.Службы.Протоколы.SoapHttpClientProtocol { public Test () { this.Url =http://localhost/SimpleWebService/Add.asmx"; } public int Add(int x, int y) { object [] results = this.Invoke("Add", // результаты new object[] {x, y}); return ((int)(results[0])); } public System.lAsyncResult BeginAddfint x, int y, System.AsyncCallback callback, object asyncState) { return this.Beginlnvoke("Add", new object[] {x, y}, callback, asyncState); } public int EndAdd(System.lAsyncResult asyncResult) { object[] results = this.Endlnvoke(asyncResult); // результаты return ((int) (results [0])); } }
Немного раньше мы показали, как получить доступ к Web-службе с помощью браузера. Вызов Web-службы с помощью браузера может оказаться полезным на этапе тестирования приложения. Но, как правило, Web-служба взаимодействует со специально разработанной для этого клиентской программой. Можно написать клиентскую программу, которая будет отсылать запрос Web-службе, используя созданные нами классы-заместители. В каталоге SimpleWebService\SimpleAddClient расположен файл Main.cs с кодом клиентской программы. Клиент реализован на языке С#. Язык С# выбран только из соображений удобства, ведь ранее созданные нами классы-заместители также написаны на С#. Клиентская программа отсылает запрос Web-службе. Web-служба вычисляет результат сложения 1 и 2, и возвращает значение 3, которое отображается в окне, представляющем консоль клиентской программы.
public class AddClient // общедоступный класс AddClient { public static void Main(string[] args) { Test 2 = new Test(); long f = z.Addd, 2); Console.WriteLine(f); return; } }
Смешивать в одном модуле языки С# и C++ нельзя. Если же вы пишите код клиентской программы на C++, его затем нужно скомпилировать и создать выполняемую сборку. Далее следует скомпилировать класс-заместитель, сгенерированный на С#, в результате чего будет получена отдельная сборка (динамически связываемая библиотека (DLL)). Таким образом, чтобы получить доступ к Web-службе, клиентская программа, написанная на C++, использует класс-заместитель, написанный на С#. Мы проиллюстрируем вышеизложенное позже в примере Arithmetic (Арифметика).