Программирование для интернета с использованием COM
Построение в VB6 COM-объекта с поддержкой доступа к данным
Возьмем созданный ранее объект "стул" и используем его в дальнейшем процессе разработки, т.е. усовершенствуем объект, добавив функции чтения и записи данных в базу данных, упорядочивание состояния экземпляра класса и его фиксирование в документе XML. В класс clsChair добавятся следующие функции.
- OpenChair(ID as string) as Boolean – открывает имеющуюся запись "стул" и заполняет объект значениями.
- CreateChair() as Boolean – генерирует новый ID, заполняет объект новым ID и записывает запись в базу данных.
- GetChairState() as XMLDOM – упорядочивает состояние объекта в XML DOM в виде: <Chair ID="" Color="" />.
В класс clsChair добавятся следующие свойства.
- ChairID as String – Read Only. Идентификатор, используемый для уникальной идентификации рассматриваемого объекта "стул".
- ChairError as String – Read Only. Описание последней обнаруженной ошибки, имевшей место в классе clsChair.
Интерфейс по-прежнему не сложен, однако теперь он более соответствует классу в истинном объектно-ориентированном программном решении. Целесообразно добавить в интерфейс и другие функции: delete (удаление) и save (сохранение) – однако для сокращения приводимых в книге примеров рассматривать их не будем.
Имя chair предшествует именам функций в классе clsChair. Создавать интерфейс к объекту, использующий имя самого объекта, не рекомендуется, однако этого требуют ограничения данной технологии. Оpen и create являются ключевыми словами, зарезервированными в VB, поэтому их нельзя использовать в качестве имен пользовательских функций в экземпляре класса. Следует заметить, что наследование класса не содержит какой-либо логики, за исключением того, что связано с описанием самого стула или с его действиями в рассматриваемом сценарии. Отсутствует логика данных или логика представления, например, строки подключения к базе данных или HTML-вывод.
В листинге 1.3 приведен общий интерфейс объекта "стул"; он содержит объявления следующих функций, включая код реализации.
clsChair Prototypes Public Property Get color() As Variant End Property Public Property Let color(ByVal vNewValue As Variant) End Property Public Property Get ChairError() As String End Property Public Property Get ChairID() As String End Property Public Function OpenChair(ID As String) As Boolean End Function Public Function CreateChair() As Boolean End Function Public Function GetChairState() As DOMDocument30 End FunctionЛистинг 1.3.
Свойства в классах
Свойства в VB представляют собой обычные функции для упрощения доступа и присвоения значений. Программист может включить в подпрограмму свойства код, реализующий работу программы. Рекомендуется создавать функции или подпрограммы для ситуаций, в которых работа выполняется программой. Хорошим примером функции в классе clsChair, являющейся свойством "только для чтения", будет GetChairState(). GetChairState() выполняет работу по созданию кода XML, поэтому она размещена в функции, возвращающей экземпляр класса. Если класс DOMDocument30 сохранен в локальной переменной класса и инициирован после вызова функции Open() или Create(), то использование свойства с доступом "только для чтения" является лучшим способом возврата экземпляра класса DOMDocument30.
Поскольку свойства ChairError и ChairID доступны только для чтения, то при попытке записи в функцию значения произойдет ошибка. Свойство color является единственным свойством, поддерживающим чтение и запись, поскольку существуют два прототипа свойства – Get и Let. Свойства ChairError и ChairID доступны только для чтения, поэтому содержат только прототип Get.
Ни в одном фрагменте кода данной лекции не показана еще одна возможность VB, которая, правда, не очень важна. Свойство может принимать и возвращать аргумент экземпляра класса. Если для принятия экземпляра класса используется прототип свойства, то используется ключевое слово Set, а не Let. Например, если класс clsChair имеет свойство записи ChairState, которое воспринимает экземпляр класса XML DOM как аргумент, то прототип выглядит следующим образом:
Public Property Set ChairState(ByVal vNewValue As DOMDocument30) End Property
Аутентификационные данные подключения к базе данных
Общей проблемой VB-приложений является неправильная поддержка абстракции логики. Если класс clsChair создан для чтения и записи данных в источник типа базы данных, то программист может включить в этот класс свойство Connection. Свойство Connection предоставляет классу информацию, необходимую для подключения к базе данных. Такой подход нежелателен, потому что возникают проблемы с расширяемостью интернет-приложений, написанных на языке VB. Интерфейс класса не отражает реальное положение дел, поскольку объект "стул" не имеет атрибута Connection на самом деле. Размещая свойство Connection в интерфейсе, программист предполагает, что потребителю класса известно, каким образом класс взаимодействует с источником данных. Атрибут Connection и подобные технические атрибуты не должны вредить интерфейсу. Здесь правильным решением является абстрагирование в бизнес-логике от всего, что не относится к объекту в реальной жизни.
Как программист может обеспечить "чистоту" логической абстракции класса и реализовать подключение к базе данных? Ввод вручную информации о подключении в классе, разумеется, не выход из положения, так как требует изменения кода. Всякое программное обеспечение должно иметь параметры состояния, доступные при инициализации или конструировании. Для сервера Windows механизмом хранения данных состояния или инициализации является реестр, который используется всеми утилитами и службами поддержки Windows. Технология .NET унаследовала использование файлов XML для хранения данных о развертывании и состоянии интернет-приложений.
Любая система работает до тех пор, пока программному обеспечению известен контекст хранения данных инициализации. Реестр Windows отыскивается всегда одинаково, независимо от узла его расположения. Программа не должна искать реестр на диске C:, ведь на другом сервере он может располагаться в другом месте. Реестр обладает контекстом, связанным с самим узлом, а не с положением файла на узле, внутри сервера или внутри сервера на отдельном узле. В интернет-приложениях корневой веб-каталог выступает в роли общего узла контекста. К содержимому или файлам можно обращаться в контексте корневого веб-каталога. Он может располагаться на диске C: или D:, и при выражении контекста как корневого веб-каталога не возникнет проблем, связанных с нахождением значения данного параметра инициализации. Платформа .NET унаследовала стандарт хранения данных развертывания в файлах XML с именем Web.config, которые располагаются в любом каталоге структуры веб-каталогов. Более подробная информация о приложениях .NET и использовании файла web.config приведена в "Веб-формы ASP.NET" и "Веб-службы ASP.NET" .
Так как класс clsChair размещен в приложении COM+, то реализован интерфейс IobjectConstruct для получения аутентификационных данных при подключении к базе данных. Для его использования в список ссылок проекта класса добавлена ссылка COM+ Services Type Library (см. рис. 1.7).
Интерфейс IObjectConstrucion реализован с использованием команды Implements, и в класс добавлена подпрограмма события IObjectConstruct_Construct. Эта подпрограмма выполняется при инициализации класса и передает экземпляр объекта классу, представляемому параметром pCtorObj. Экземпляр класса, на который указывает pCtorObj, имеет свойство ConstructString. Значение ConstructString использовалось для инициализации объекта ADO Connection, повсеместно применяемого в классе clsChair. В листинге 1.4 показана подпрограмма события IObjectConstruct_Construct.
IObjectConstruct_Construct event subroutine implementation in clsClass Option Explicit Implements IObjectConstruct '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' ***** constants to class ***** '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'old style connection string in case nothing else works Private Const DEFAULT_CONSTRUCTION_STRING = _ "driver={Microsoft Access Driver (*.mdb)};" & _ "dbq=D:\aspData\employees.mdb" Private Const DEFAULT_COLOR = "Brown" Private Const CHAIR_ID = "ID" Private Const CHAIR_COLOR = "Color" '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' ***** locals to class ***** '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'holds the color of the chair Private m_scolor As String 'Chair ID for class instance Private m_sID As String 'holds the ADO Connection to the data 'source that the object interacts with Private m_Connection As ADODB.Connection Private m_sErrorMessage As String Private Sub IObjectConstruct_Construct(ByVal pCtorObj As Object) On Error GoTo Sub_Error_Handler Const ERROR_MESSAGE_INFO = "IObjectConstruct_Construct" Dim sConnection As String sConnection = pCtorObj.ConstructString 'make certain there is something If Len(sConnection) < 1 Then sConnection = DEFAULT_CONSTRUCTION_STRING End If 'establish connection to database server If m_Connection Is Nothing Then Set m_Connection = CreateObject("ADODB.Connection") End If m_Connection.Open sConnection 'DEFAULT_CONSTRUCTION_STRING 'establish connection to database server Set m_Connection = CreateObject("ADODB.Connection") m_Connection.Open sConnection '"DSN=ASPExample" '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sub_Exit_Done: Exit Sub Sub_Error_Handler: 'record the error in class instance and rethrow 'for consuming software to learn of issue ProcessErr ERROR_MESSAGE_INFO & _ " Failure obtaining database connection information." & _ " Class will not connect to database" End SubЛистинг 1.4.
Значение свойства ConstructString устанавливается в окне свойств службы компонентов. Для clsClass строка подключения задана в текстовом поле Constructor String (Строка конструктора) вкладки Activation (Активация) окна свойств компонента ConfigSeat.clsClass (см. рис. 1.18). При использовании данного механизма хранения данных о состоянии инициализации класс clsChair настраивается при помощи обычных служб Windows Server, с которыми знаком любой инженер, обслуживающий такой сервер.
Примечание. Технология доступа к данным Windows, использующая технологию ODBC или OLE-DB, позволяет автоматически сохранять подключения к базе данных. Экземпляр класса подключения ADO, хранящийся в m_Connection, является локальным по отношению к классу clsChair (см. рис. 1.4). Это означает, что подключение открыто, пока существует экземпляр класса clsChair. При уничтожении экземпляра класса clsChair экземпляр подключения ADO уничтожается, однако провайдер ODBC или OLE-DB сохраняет экземпляр подключения для следующего запроса. Не нужно кэшировать объекты подключения или создавать ситуации, требующие кэширования, поскольку Windows и так выполняет эту функцию.