Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Proxy с ранним связыванием






Объект SOAPClient30, входящий в SOAP Toolkit, удобен в использовании, но вызовы методов происходят с помощью динамического интерфейса IDispatch..

Чтобы упростить жизнь клиенту и заодно избежать накладных расходов IDispatch-интерфейса, мы реализуем Proxy, которая будет принимать вызовы через vtable и использовать низкоуровневый API для передачи этих вызовов на сервер. Применение такой Proxy в коде клиента имеет два существенных преимущества по сравнению с SOAPClient30:

  • Упрощается вызов методов, так как вызов IDispatch:: Invoke на VC++ требует написания большого количества кода.
  • Устраняются накладные расходы IDispatch.

Чтобы спроектировать Proxy, нам надо разобраться с последовательностью вызовов низкоуровневых объектов:

  • Прежде всего, необходимо разобрать WSDL- и WSML-файлы, найти нужный сервис, порт и операцию:
Dim r As WSDLReader30 Dim es As IEnumWSDLService Dim s As IWSDLService Dim ep As IEnumWSDLPorts Dim p As IWSDLPort Dim eo As IEnumWSDLOperations Dim o As IWSDLOperation Dim em As IEnumSoapMappers Set r = New WSDLReader30 r.Load " https://ivan/TView/TView.wsdl", " https://ivan/TView/TView.wsml" r.GetSoapServices es es.Find " TView", s s.GetSoapPorts ep ep.Find " TViewSoapPort", p p.GetSoapOperations eo eo.Find " GetProcesses", o o.GetOperationParts em
  • Теперь мы можем задать значения входных параметров, используя ISoapMapper:: ComValue.
  • Когда входные параметры заданы, мы готовы к передаче запроса серверу. Нам понадобится коннектор:
Set ocnf = New SoapConnectorFactory30 Set ocn = ocnf.CreatePortConnector(p) ocn.Property(" SoapAction") = o.SoapAction ocn.ConnectWSDL p
  • Запрос преобразуется в XML с помощью объекта SoapSerializer30:
Set ss = New SoapSerializer30 ss.InitWithComposer ocn.InputStream, composer ss.StartEnvelope ss.StartBody " STANDARD" o.Save ss, True ss.EndBody ss.EndEnvelope ss.Finished ocn.EndMessage
  • Вызов EndMessage означает, что вызов был передан серверу, и мы можем получить результат:
Set sr = New SoapReader30 sr.LoadWithParser ocn.OutputStream, Parser o.Load sr, False
  • Значения выходных параметров могут быть получены с помощью вызова ISoapMapper:: ComValue. Если вызов завершился с ошибкой, информация о ней будет доступна через свойства объекта SoapReader30.

Код будет одинаков для вызова любых методов серверного компонента. Изменяться будут только имя операции и работа с входными и выходными параметрами с помощью интерфейса ISoapMapper. Кроме того, код можно разбить на две части – первая часть (разбор WSDL и WSML, создание компонентов) выполняется однократно, другая часть (получение операции, заполнение параметров, сериализация в XML) выполняется при каждом вызове.

Интерфейс нашего Proxy-объекта будет таким:

Метод Описание
Initialize(WSDL, WSML, Service, Port) Инициализация. Разбор WSDL и WSML, создание вспомогательных компонентов.
ConnectorProperty Позволяет изменять свойства коннектора.
ProxyProperty Позволяет изменять свойства Proxy. Мы будем поддерживать одно свойство – ConnectorProgID, позволяющее заменять коннектор.
GetOperation(Name) Возвращает операцию из WSDL по имени.
ExecuteOperation(op) Выполняет указанную операцию. В случае ошибки генерирует IErrorInfo.

В лучших традициях компонентов SOAP Toolkit потоковая модель Proxy будет ‘Both’. Компонент будет агрегировать FTM (Free Threaded Marshaler).

Реализация методов Proxy полностью повторяет приведенный выше код на VB. Интерес представляет только обработка ошибок, которые может возвратить сервер – если после вызова ISoapReader:: Load свойство Fault ненулевое, значит, сервер вернул ошибку. Ее код и описание нужно получить, используя объектную модель MS XML.

XML:: IXMLDOMElementPtr spFault; CheckError(spReader-> get_FaultDetail(& spFault)); if(spFault) { // сервер вернул ошибку HRESULT hCode = E_FAIL; XML:: IXMLDOMNodeListPtr spList = spFault-> getElementsByTagName(OLESTR(" mserror: returnCode")); if(spList-> length) { hCode = _wtol(spList-> item[0]-> text); } _bstr_t description; spList = spFault-> getElementsByTagName(OLESTR(" mserror: description")); if(spList-> length) { description = spList-> item[0]-> text; } _bstr_t source; spList = spFault-> getElementsByTagName(OLESTR(" mserror: source")); if(spList-> length) { source = spList-> item[0]-> text; }... // создаем IErrorInfo _com_error e(hCode, spInfo, true); throw e; }

Чтобы использовать раннее связывание, т.е. вызов через vtable, мы создадим новый компонент и при помощи ATL-мастера “Implement Interface” добавим реализацию нужного интерфейса. Теперь в каждый метод интерфейса нужно добавить код, перенаправляющий вызов к нашей Proxy. Например, реализация метода GetProcesses, возвращающего один выходной параметр, может быть такой:

STDMETHOD(GetProcesses)(_Recordset * * ppRecordset) { try { IWSDLOperationPtr spOp = m_spSoapProxy-> GetOperation(L" GetProcesses"); m_spSoapProxy-> Execute(spOp); IEnumSoapMappersPtr spEnum; spOp-> GetOperationParts(& spEnum); while(true) { long l = 0; ISoapMapperPtr spMap; spEnum-> Next(1, & spMap, & l); if(l == 1) { if(spMap-> PartName == _bstr_t(L" Result")) { CheckError(spMap-> ComValue.punkVal-> QueryInterface(IID__Recordset, (void**)ppRecordset)); } } else break; } } catch(_com_error & e) { return e.Error(); } return S_OK; }

В состав Visual Studio.NET входит генератор Proxy с ранним связыванием для протокола SOAP - sproxy.exe. С его помощью можно сгенерирован компонент, использующий поддержку SOAP в ATL 7.0 для передачи вызовов серверу. Генератор работает на основе WSDL-файлов. Главный недостаток этого генератора связан с тем, что полученный код будет компилироваться только VC++ 7.0 и ATL 7.0, поэтому для приложений, использующих SOAP Toolkit и/или написанных в VC++ 6.0 этот генератор непригоден.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.