Программирование для интернета с использованием COM
Структурирование данных в XML
Функция GetChairState создает документ XML, описывающий экземпляр класса clsChair. XML является простым одноэлементным документом. Элемент Chair содержит два атрибута: ID и Color. Для использования объекта XML добавьте в проект ссылку на библиотеку MSXML (см. рис. 1.7). В нашем проекте выбрана библиотека Microsoft XML v3.0, но существуют и другие версии этой библиотеки. На момент публикации книги уже вышла четвертая версия. В подпрограмме применяется конкатенация строк для построения XML и возврата строки из класса. Однако такой подход опасен, поскольку в большинстве XML-анализаторов сразу возникнет ошибка при некорректности любой части XML. Создание XML с использованием анализатора позволит правильно построить XML. В листинге 1.12 приведен исходный код функции GetChairState.
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' ChairID - read only '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Public Property Get ChairID() As String ChairID = Trim(m_sID) End Property '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'GetChairState 'serializes object state into XML DOM 'to look like this <Chair ID="" Color="" /> ' 'in: nothing 'out: returns DOMDocument30 object filled '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Public Function GetChairState() As DOMDocument30 On Error GoTo Sub_Error_Handler Const ERROR_MESSAGE_INFO = "GetChairState" Const CHAIR_ELEMENT = "Chair" Const CHAIR_ID_ATTRIBUTE = "ID" Const CHAIR_COLOR_ATTRIBUTE = "Color" Dim xmlChair As MSXML2.DOMDocument30 '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'note : Constructing the XML using 'string concatenation and using the 'XML object to validate is another 'strategy often times used. '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'refresh the object OpenChair Me.ChairID 'build XML document Set xmlChair = New DOMDocument30 'create the element for Chair Set xmlChair.documentElement = _ xmlChair.createElement(CHAIR_ELEMENT) 'add the Chair attributes xmlChair.documentElement.setAttribute _ (CHAIR_ID_ATTRIBUTE), ChairID xmlChair.documentElement.setAttribute (CHAIR_COLOR_ATTRIBUTE), color '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sub_Exit_Done: 'return object Set GetChairState = xmlChair On Error Resume Next 'destroy objects Set xmlChair = Nothing Exit Function Sub_Error_Handler: ProcessErr " Failure serializing chair into XML. " End FunctionЛистинг 1.12. Function GetChairState
После изучения кода в листинге 1.12 становится ясно, почему при построении XML используется конкатенация строк. Применение DOM Document интуитивно непонятно, и кажется, что для построения форматированной строки выполняется очень большой объем работы. Первая версия библиотеки XML MSXML.DLL была медленной и неэкономичной с точки зрения ресурсов; здравомыслящий программист реализует XML гораздо быстрее конкатенацией строк. Язык VB не достаточно эффективен для этого. Сокращение изменений, вносимых в строку, кардинально улучшает производительность. Поскольку технологии, связанные с XML, являются довольно новыми, программное обеспечение, поддерживающее эти технологии, должным образом не "устоялось". Программист должен быть в курсе новых данных от производителя и авторов статей и книг, так как данная технология постоянно модернизируется.
Расширенная тестовая структура
Новый класс clsChair можно протестировать после расширения тестовой структуры (см. рис. 1.8) для проверки созданного интерфейса. В тестовую структуру были добавлены кнопки Get XML (Получить XML), Open (Открыть) для открытия нового экземпляра объекта "стул" и Create (Создать) (см. рис. 1.19). Перед нажатием на кнопку Open (Открыть) укажите в текстовом поле аргумент стула ID.
Настройка совместимости с двоичными файлами в VB
Если при перекомпиляции ConfigSeat.dll не скомпилирована тестовая структура, то может возникнуть ошибка при создании экземпляра класса. Это возможно для любого COM-объекта, если другая программа использует COM-объект и содержит ссылки на него. В VB проект ActiveX DLL настраивается на совместимость с проектом по умолчанию во вкладке Component (Компонент) окна свойств проекта. При перекомпиляции рассматриваемого проекта ActiveX DLL не будет установлена совместимость с двоичными файлами, поэтому при выполнении других программ со скомпилированными ссылками на библиотеку ActiveX DLL возникнут ошибки.
Для иллюстрации вышесказанного рассмотрим следующую ситуацию: ConfigSeat.dll скомпилирована в 9:00 утра. В полдень скомпилирована тестовая структура с именем testconfigseat.exe. Тестовая структура testconfigseat.exe содержит определенные ссылки на ConfigSeat.dll, и в ее коде класс озаглавлен строго определенным образом. В 18:00 проект ConfigSeat.dll перекомпилирован и установлена совместимость с проектом. При выполнении в 18:08 файл testconfigseat.exe вызвал ошибку, поскольку не смог найти библиотеку ConfigSeat.dll из-за изменения CLSID. При каждой компиляции ConfigSeat без указания совместимости с двоичными файлами генерируется новый CLSID. После настройки компонента на совместимость с двоичными файлами (см. рис. 1.20) VB использует один и тот же CLSID при каждой компиляции DLL, поэтому любое зависимое от библиотеки программное обеспечение работает исправно.
Приложение, использующее библиотеку ActiveX DLL, ожидает интерфейс для данного CLSID. Изменение интерфейса класса иначе, чем добавлением новой функции или свойства, вызовет ошибки в приложениях-потребителях, работа которых основывается на классе.
Рис. 1.20. Во вкладке Component (Компонент) окна свойств проекта установлена совместимость с двоичными файлами
Вы можете добавить новые функции, однако нельзя изменить или удалить имеющиеся параметры. Для имени библиотеки и класса идентификатор CLSID остается неизменным, что достигается компиляцией, совместимой с двоичными файлами. Преимуществом совместимости с проектами является то, что программист может ссылаться на проект ActiveX DLL и легко изменять интерфейсы внутренних классов. Поскольку при программировании интерфейс меняется, совместимость с проектами позволит VB разрешить изменения, не предупреждая о нарушении совместимости при удалении или редактировании общей функции.
Загрузка в COM+ с помощью строки Constructor
ConfigSeat.dll можно скопировать в среду сервера и разместить в приложении COM+, заменив предыдущую версию ConfigSeat.dll. Приложение COM+ в службах компонентов может заблокировать DLL. После отключения приложение в службах компонентов библиотека DLL освобождается для удаления. Если библиотека DLL участвует в работе веб-приложения, то веб-сервер не будет использовать класс clsChair после удаления классов в DLL из приложения COM+.
Сейчас мы выполним загрузку новой версии clsClass в приложение COM+ New ConfigSeatWeb.
- В консоли управления службами компонентов удалите старую версию ConfigSeat.clsClass, щелкнув правой кнопкой мыши на компоненте и выбрав Delete (Удалить).
- Добавьте новую версию компонента так же, как и первую версию, с помощью мастера установки компонентов COM+ (COM+ Component Install Wizard ).
- По окончании работы с мастером щелкните правой кнопкой мыши на классе в консоли управления Component Services и выберите Properties (Свойства), чтобы открыть окно свойств для класса ConfogSeat.clsClass.
- Откройте вкладку Activation (Активация) и отметьте опцию Enable Object Construction (Включить конструирование объекта). Затем введите текст, который должен получить класс от подпрограммы события IObjectConstruct_Construct, приведенной в листинге 1.4. В классе ConfigSeat.clsClass строка конструктора содержит строку подключения ADO для получения доступа к информации в базе данных (см. рис. 1.18).
- Убедитесь, что класс clsChair загружен, выполнив на нем быстрый модельный тест. Тестовая структура проясняет функциональность класса внутри новой среды. Исполняемый файл скопируйте на узел и запустите. Выполните более простой тест с помощью DescribeChair.asp (см. листинг 1.2), добавив несколько новых вызовов функций для нагрузки компонента. В листинге 1.13 приведена расширенная версия файла DescribeChair.asp с именем DescribeChairFinal.asp.
<%@ Language=VBScript %> <HTML> <HEAD> </HEAD> <BODY> <% dim i dim o dim oXML Response.Write("<p>start Test</p>") 'create the object since this is hard work set o = Server.CreateObject("ConfigSeat.clsChair") 'demonstrate that values were changing Response.Write("<p> color=" & o.color & "</p>") Response.Write("<p>change color to blue</p>") o.color = "blue" Response.Write("<p> color=" & o.color & "</p>") if o.CreateChair() then Response.Write("<p> new id=" & o.ChairID & "</p>") else Response.Write("<p> possible error=" & o.ChairError & "</p>") end if set oXML = o.GetChairState() Response.Write("<p> xml=" & oXML.XML & "</p>") Response.Write("<p> open new chair</p>") if not o.OpenChair("20021129095221") then Response.Write("<p> possible error=" & o.ChairError & "</p>") end if Response.Write("<p> new chair color should be purple</p>") Response.Write("<p> new chair color =" & o.color & "</p>") 'destroy object so it can be created again set o = nothing %> </BODY> </HTML>Листинг 1.13. DescribeChairFinal.asp used to demonstrate added interface of clsChair.
Запустите тест нагрузкой из утилиты Microsoft Application Center Test, и вы увидите, что работа приложения ASP – COM – база данных требует больше ресурсов, чем простое приложение ASP – COM. Предыдущая версия clsChair не предусматривает взаимодействия с базой данных, и база данных располагается на том же сервере, где расположены ASP и COM-объект clsChair. При моделировании одновременной работы 100 пользователей в течении 5 минут выяснилось, что приложение способно поддерживать среднюю нагрузку, равную 45 запросам на страницы в секунду.
На рисунке 1.17 показано окно служб компонентов, отображающее состояние предыдущего теста. В тесте для предыдущей версии clsChair заголовки Call и Call Time не регистрировали никаких значений, кроме 0. В последней версии clsChair поле In Call стабильно отображало значения от 0 до 1, а поле Call Time стало равным 15 мс. Очевидно, что производительность компонента заметно снизилась по сравнению с проведенным ранее тестом. Как видите, дополнительная функциональная нагрузка, связанная со считыванием информации из базы данных, снижает эффективность работы веб-приложения.