This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Издательский дом "Вильяме" Москва • Санкт-Петербург • Киев 2002
ББК 32.973.26-018.2.75 Ф83 УДК 681.3.07 Издательский дом "Вильяме" Зав. редакцией В. В. Александров Перевод с английского В.Г. Барышникова и И.В. Шуляк Под редакцией В. В. Александрова По общим вопросам обращайтесь в Издательский дом "Вильяме" по адресу: [email protected], http://www.williamspublishing.com
Франклин, Кит. Ф83
VB.NET для разработчиков. ; Пер. с англ. — М. : Издательский дом "Вильяме", 2002. - 272 с.: ил. - Парал. тит. англ. ISBN 5-8459-0241-Х (рус.) Основная задача книги — быстро ознакомить разработчиков Visual Basic с изменениями в .NET Framework. Программисты, использующие Java, C++, Delphi или другие инструменты разработки приложений и интересующиеся Visual Basic или технологией .NET Framework, также найдут эту книгу полезной. Хотя книга посвящена Visual Basic.NET, ее основная цель— продемонстрировать взаимодействие Visual Basic и .NET Framework. Книга знакомит с новой парадигмой разработки программного обеспечения, представленной .NET Framework, включая ASP.NET, Windows Forms и Web-службы. Книга предназначена для опытных программистов-практиков. ББК 32.973.26-018.2.75
ГЛАВА 3. Концепции объектно-ориентированного программирования
43
ГЛАВА 4. Методы, свойства, события
57
ГЛАВА 5. Создание и удаление объектов
69
ГЛАВА 6. Создание проектов VB.NET
75
ГЛАВА 7. Типы данных и объектов
111
ГЛАВА 8. Управление порядком выполнения команд
125
ГЛАВА 9. Обработка ошибок
137
ГЛАВА 10. ADO.NET
153
ГЛАВА 1 1 . Проектирование, архитектура и реализация приложений .NET Framework
175
ГЛАВА 12. Взаимодействие элементов языка
193
ГЛАВА 13. Переход с Visual Basic 6.0
217
ГЛАВА 14. Будущее .NET Framework
229
ПРИЛОЖЕНИЕ А. Приложение Windows Form
233
ПРИЛОЖЕНИЕ Б. Web-служба ASP.NET и приложения Web Forms
245
Предметный указатель
260
Содержание Об авторах Благодарности Введение Для кого предназначена эта книга Требования к программному обеспечению ГЛАВА 1. Среда .NET Framework Сборки Закрытые сборки Общедоступные сборки Метаданные Common Language Runtime Компиляция по требованию Управление версиями Пространства имен Библиотека классов .NET Framework Развертывание приложений Резюме
11 12 13 13 14
.
15 15 17 17 18 19 19 20 21 23 24 25
ГЛАВА 2. Visual Studio.NET Введение в Visual Studio.NET Интегрированная среда разработки Visual Studio.NET Редактор кода Visual Studio.NET Свертываемые блоки кода Автоматическое форматирование и завершение ввода кода Включение URL в код и комментарии Другие редакторы Visual Basic и .NET Framework Введение в VB.NET Цели проектирования VB.NET Доступность Поддержка объектно-ориентированного программирования Современные языковые конструкции Безопасность Многоязычная интеграция Взаимодействие с СОМ и Windows API Резюме
ГЛАВА 3. Концепции объектно-ориентированного программирования Абстрагирование в Visual Basic.NET Инкапсуляция в VB.NET Полиморфизме VB.NET Наследование в VB.NET Реализация наследования Включение Программирование интерфейсов Изменения интерфейсов в VB.NET Резюме
43 44 45 46 48 49 51 52 53 55
6
Содержание
ГЛАВА 4. Методы, свойства, события Методы Изменения параметров Вызов процедуры Возврат значений Общедоступные методы Перегрузка функции Свойства Общедоступные свойства События Делегаты Обработчики событий Создание событий Генерация событий Использование EventArgs Атрибуты Резюме
ГЛАВА 5. Создание и удаление объектов Конструкторы Деструкторы Модификаторы доступности Модификаторы классов Модификаторы методов и свойств Резюме
69 69 71 72 72 73 74
ГЛАВА 6. Создание проектов VB.NET Неподдерживаемые типы проектов Библиотеки классов Приложения Web Form Создание приложения Web Form Элементы управления Web Form Проекты Web Service Приложения Windows Элементы управления Windows Службы Windows Консольные приложения Резюме
75 75 75 80 81 86 92 96 102 107 109 110
ГЛАВА 7. Типы данных и объектов Типы в .NET Framework Численные типы Ссылочный тип данных Обработка строк Класс System. String Класс System.Text.StringBuilder Пакетирование и распаковка Встроенные типы данных B V B . N E T Тип Date Тип Decimal Типы Short, Integer, Long Тип Object
ГЛАВА 8. Управление порядком выполнения команд Выражения с сокращенным циклом Операторы выбора Итерация или операторы цикла Неиспользуемые операторы Резюме
125 125 126 129 136 136
ГЛАВА 9. Обработка ошибок Класс System.Exception Оператор Try...Catch...Finally Предложение Try Оператор Exit Try Предложение Catch Предложение Finally Оператор Throw Реализация структурной обработки исключений Размещение исключений Гарантия выполнения очистки кода Создание пользовательских типов исключения Глобальные обработчики исключений Эффективное использование структурной обработки исключений Произвольное создание собственных типов исключений Добавление всего кода в обработчик исключений Замена кода условий обработчиками исключений Возврат всех исключений к вызывающему оператору Пример приложения Windows Form, использующего обработку исключений Резюме
Remote Data Objects OleDBnADO ADO.NET Объектная модель ADO.NET Объект OleDBConnection Объект OleDBCommand Объект OleDBDataReader Объект OleDbDataAdapter Объект OleDbException Пакетные обновления Объект DataSet Объект DataTable Объект Data Relation Поддержка ADO.NET в Visual Studio.NET Строгая типизация объектов DataSet Резюме 8
ГЛАВА 1 1 . Проектирование, архитектура и реализация приложений .NET Framework Безопасность Идентичность кода Защита доступа к коду Декларативная безопасность Императивная безопасность Ролевая безопасность Система удаленной безопасности Криптография Сборка мусора и управление ресурсами Управление ресурсами на основе СОМ-технологии Управление ресурсами среды .NET Framework Вопросы эффективности Масштабируемость и эффективность Взаимодействие Численные типы Не злоупотребляйте методом Finalize Избегайте метода On Error Использование библиотеки классов .NET Framework Архитектурный анализ Windows DNA, DNA 2000 и .NET Framework Многоуровневая архитектура в .NET Framework Серверы .NET Enterprise Интеграция XML SOAP Web-службы Создание Web-службы
ГЛАВА 12. Взаимодействие элементов языка Вызов API Windows Оператор Declare Управление маршалингом Структура оператора Declare Использование компонентов .NET Framework в СОМ-приложениях Создание "строгих" имен Помещение в глобальный кэш сборок Регистрация Создание библиотеки типов Сквозной контроль Использование компонентов СОМ из приложений .NET Framework Службы СОМ+ Применение служб СОМ+ Написание компонентов .NET Framework, которые взаимодействуют со службами СОМ+ Резюме
ГЛАВА 13. Переход с Visual Basic 6.0 Элементы Visual Basic 6.0, измененные в VB.NET Типы проектов Конструкции языка
217 217 217 218
Содержание
206 216
9
Недокументированные возможности Изменения в языке
220 220
Переход от V B 6 . 0 K V B . N E T
221
Схема миграционного процесса Анализ миграционного процесса Создание нового приложения Visual Basic 6.0 Используйте стандартные документы Обучение Явное объявление План изменений Использование ХМ L Резюме
222 225 225 226 226 226 227 227 227
ГЛАВА 14. Будущее .NET Framework Кроссплатформенность .NET Framework Дополнительные Web-службы Краткий обзор Hailstorm Интеграция .NET Framework и .NET Enterprise Servers Резюме
229 229 229 230 231 232
ПРИЛОЖЕНИЕ А. Приложение Windows Form Обработка данных спортивной статистики Источник данных приложения Загрузка дерева Меню Создание новых записей Визуальное наследование Резюме
233 234 236 236 239 240 241 243
ПРИЛОЖЕНИЕ Б. Web-служба ASP.NET и приложения Web Forms Web-служба спортивной статистики Обработка статистических данных Узел бейсбольной статистики Резюме
245 246 252 256 259
Предметный указатель
260
10
Содержание
Об авторах Кит Франклин (Keith Franklin) — президент и главный архитектор американской консалтинговой компании Empowered Software Solution (ESS), находящейся в городе Напервиль, штат Иллинойс. Кроме того, он постоянный сотрудник компьютерных журналов Visual Basic Programmers Journal и Visual Studio Magazine, а также постоянный докладчик на конференции для разработчиков на Visual Basic — VBITS (Visual Basic insiders technical summit). Кит— руководитель конференции Chicago.NET Users Group и один из главных архитекторов проекта www. d o t - n e t r o c k s . corn, созданного совместно с Роком Лготкой (Rocky Lhotka). Как архитектор компании ESS, Кит консультирует, обучает и проектирует решения для клиентов, создающих приложения с высоким уровнем масштабируемости для Internet, системы электронной коммерции и распределенные приложения типа клиент/сервер. Кит создает приложения на базе .NET Framework, ASP.NET и VB.NET с момента появления первой бета-версии .NET Framework. Общаться с Китом можно через Web-узел компании ESS (www.empowered.com) или с помощью электронной почты: [email protected]. Ребекка М. Риордан (Rebecca M. Riordan) имеет двадцатилетний опыт проектирования программного обеспечения и заработала международное признание как консультант, системный аналитик, разработчик баз данных и вспомогательных систем. Она принимала участие в ведущих проектах на территории США, Австралии и Европы, а также руководила отделом профессионального обслуживания в одной из крупнейших австралийских компаний и работала старшим техническим инженером в Microsoft. Сейчас Ребекка проживает в Нью-Мексико. Она автор книг Designing Relational Database Systems, SQL Server 2000 Programming Step by Step и готовящейся к изданию ADO.NET Step by Step.
Об авторах
11
Я посвящаю эту книгу жене и детям. В течение последних шести месяцев я уделял им слишком мало времени (особенно Тэми), так как был вынужден с головой зарыться в документацию (особенно когда материал казался недостаточно ясным для понимания). Тэми, ты наполняешь мою жизнь смыслом и я люблю тебя всем сердцем, ты— моя душа! Ты создала теплую, счастливую семью, и я дорожу этим больше всего на свете — без тебя ничто не имело бы смысла. У меня два чудных маленьких мальчика, и мы ожидаем появления еще одного ребенка. Всякий раз, когда я слышу смех Скотти иДжеффи, мне кажется, что солнце сияет ярче. Скотти, когда я вижу, как ты гоняешь на своем детском автомобильчике, отчаянно призывая помочь тебе остановиться, я плачу от смеха. Я смеюсь потому, что ты такой забавный; я любуюсь тобой, глядя, как быстро ты растешь. Джеффи, ты маленький папочкин комик; хотя внешне ты похож на маму, умом и сарказмом ты определенно в меня. Когда ты даришь мне свою озорную улыбку, я становлюсь немного моложе. Ты — мое сердце! Я хотел бы также посвятить эту книгу моему отцу, матери, братьям и сестре. Особенно отцу. Отец, ты даже не представляешь, как много хорошего твои дети взяли от тебя. Неважно, сколько мы могли спорить с тобой о спортивных командах Чикаго, мы все любим и уважаем тебя. Прежде всего благодаря тебе мы выросли добрыми и сострадательными людьми. Я люблю тебя, папа, и твои внуки обожают тебя.
Благодарности Писать книгу, посвященную продукту, который находится в стадии разработки, — задача далеко не из легких. Приходится привлекать множество спецшшистов; некоторых из них мне хотелось бы поблагодарить отдельно. Прежде всего речь идет о руководителе проекта Неле Роуве (Nell Rowe), который держал весь процесс создания книги под контролем, и техническом редакторе Ребекке Риордан (Rebecca Riordan), оказавшей помощь в структурировании книги, что позволило сделать ее более ясной. Также я хотел бы выразить признательность компании Microsoft за создание превосходного продукта. И особенно разработчикам Visual Studio.NET и .NET Framework. Эта платформа и инструментарий на уровень выше всего того, что было разработано прежде. Хотелось бы поблагодарить сотрудников Microsoft, которые потратили много сил и времени, предоставляя необходимую информацию о продукте. Наконец, я очень благодарен моим талантливым партнерам и разработчикам из компании Empowered Software Solution. Это признание — только первое доказательство того, что наша цель создания высококвалифицированной консалтинговой компании, предназначенной для обучения разработчиков, вполне оправдывает себя.
12
Благодарности
Введение С момента представления первой версии Visual Basic в 1991 году разработка Windowsприложений начала доминировать при создании программного обеспечения благодаря появлению средств быстрой разработки приложений (Rapid Application Development — RAD). Но, после того как процесс создания Internet-ориентированных приложений достиг этапа зрелости, потребовалась более эффективная модель разработки Windows- и Internet-приложений. Пытаясь заработать на Internet, Microsoft изменила назначение и архитектуру ActiveX для того, чтобы облегчить процедуру внедрения этой технологии в обозреватель Internet. Для разработки клиентской части приложений Microsoft создала облегченную версию Visual Basic, известную как VBScript. Кроме того, была проведена модернизация самого Visual Basic, цель которой состояла в том, чтобы сделать его лучшим инструментом компонентной разработки. Эта работа была уже на втором этапе, включавшем создание обновленного инструментария для разработки приложений с использованием технологий Java и Active Server Pages, когда Microsoft приступила к проектированию абсолютно новой программной модели для разработки Windows- и Internet-приложений. В результате была создана технология .NET Framework, представленная в июле 2000 года на конференции профессиональных разработчиков Microsoft (Microsoft Professional Developers Conference). Технология .NET Framework— это комплексная платформа для построения Internetсистем, позволяющая также создавать стандартные полнофункциональные Windowsприложения. Она включает обширную библиотеку классов, покрывающую потребности разработчиков при решения большинства задач. В дополнение к этому .NET Framework предоставляет разработчикам интегрированные средства безопасности, кроссплатформенного взаимодействия, управления ресурсами и масштабируемости. Позиционируя .NET как платформу для будущих Windows-систем, Microsoft была вынуждена внести в Visual Basic.NET значительные изменения. Разработчики Visual Basic находят эти изменения потрясающими, с одной стороны, и довольно неудобными — с другой. Как сказал Йода в пятой серии кинофильма Звездные войны. Империя наносит ответный удар: "Вы должны забыть то, что изучили раньше". Как правило, это не проблема, поскольку .NET Framework почти всегда предоставляет более элегантный способ решения задачи, которая требовала больших усилий в предыдущей версии Visual Basic. Цель данной книги — помочь вам быстрее освоить Visual Basic.NET и обратить внимание на изменения, внесенные в Visual Basic при переходе в среду .NET Framework.
Для кого предназначена эта книга Основная задача книги — быстро ознакомить разработчиков Visual Basic с изменениями в .NET Framework. Программисты, использующие Java, C++, Delphi или другие инструменты разработки приложений и интересующиеся Visual Basic или технологией .NET Framework, также найдут эту книгу полезной. Хотя книга посвящена Visual Basic.NET, ее основная цель— продемонстрировать взаимодействие Visual Basic и .NET Framework. Данная книга знакомит с новой парадигмой разработки программного обеспечения, представленной .NET Framework, включая ASP.NET, Windows Forms и Web-службы.
Введение
13
Требования к программному обеспечению Для разработки приложений с использованием Visual Basic.NET необходимо установить Visual Studio.NET. Пакет Visual Studio.NET доступен для загрузки через Internet подписчикам MSDN Universal или может быть заказан на компакт-дисках. Для тестирования продукта рекомендуется использовать компьютер, работающий под управлением операционной системы Windows 2000 или Windows XP. К моменту написания книги .NET Framework еще находилась в стадии тестирования, хотя многие компании и организации уже давно используют эту технологию для развертывания своих приложений. Билл Гейтс на конференции TechEd, проходившей в июне 2001 года в Атланте, сказал, что Visual Studio.NET Beta 2 — самая надежная тестовая версия, которую он когда-либо видел.
14
Введение
ш
ГЛАВАМ, Среда .NET Framework В середине 90-х годов парадигма разработки программного обеспечения начала быстро изменяться в основном за счет существенного снижения стоимости вычислительной техники и стремительного роста Internet. В соответствии с этой тенденцией компания Microsoft изменила подход к разработке программного обеспечения для платформы Windows. Эти изменения в конечном счете привели к созданию среды .NET Framework. Первый вариант среды исполнения объектов появился в 1997 году, когда Microsoft представила сервер MTS (Microsoft Transaction Server). Вскоре после этого Microsoft начала разработку новой операционной системы Windows NT 5, которая стала впоследствии называться Windows 2000, и новой версии СОМ, получившей название СОМ+. Технология СОМ+ первоначально содержала два компонента: СОМ+ Services, который предоставлял доступ к службам с помощью административных программных средств (замена прямым вызовам API), и СОМ+ Runtime, который перекладывал реализацию сложных функций поддержки СОМ-объектов с разработчиков на операционную систему. В то же время Microsoft активно исследовала такие параллельно развивающиеся технологии, как Java и XML. Собрав лучшие идеи, заложенные в этих технологиях, компания Microsoft дополнила их и реализовала в своих продуктах. Все это в конечном счете объединилось в один продукт, известный как Next Generation Web Services (NGWS), который впоследствии получил название .NET Framework (рис. 1.1).
Сборки В среде Windows всегда возникали проблемы при развертывании приложений. Одна из наиболее распространенных проблем, так называемый DLL-кошмар (DLL Hell), связана с установкой на компьютеры библиотек динамической компоновки (DLL) разных версий, принадлежащих различным приложениям или их модификациям.
С VsiualBasci
C#
jC~
JScript
C++
Языки сторонних разработчиков
Спецификация единого языка
nIe trnetExp ole rr С
Основные компоненты среды исполнения .NET ASP.NET
Элементы управления
Web-службы I Web Forms s
J V
•
J
Оболочка 'Консольные ] [ Windows ^приложениям I Forms ^Службы NTJ
Базовые классы .NET Framework
Единая среда исполнения | (Управление памятью)
(
Сборка мусора
)
(
) О^олГГ" ) I
Рис. 1.1. Компоненты.NET Framework
В настоящее время существует несколько способов проявления описанной проблемы. Если какое-то приложение в процессе загрузки замещает в оперативной памяти существующую библиотеку динамической компоновки более старой версией, то это приводит к сбою в работе других приложений, использующих данную библиотеку. Или же новая версия библиотеки, соответствующая модели компонентных объектов (COM DLL), разрушает старые приложения из-за несоблюдения требований совместимости с предыдущей версией. Проблема с библиотеками, не поддерживающими СОМ, осложняется тем, что эти библиотеки могут быть загружены из любого места системы. Если несколько приложений на одном компьютере используют разные версии одной библиотеки, то эти приложения могут загружать соответствующие библиотеки из разных мест. Однако, поскольку Windows всегда пытается использовать уже загруженную в память библиотеку, не дожидаясь загрузки другой, приложения могут останавливаться в самый непредсказуемый момент, в зависимости от порядка загрузки их в память. Реализуя технологию COM (Component Object Model), разработчики Microsoft попытались решить проблему вызова соответствуюших приложению библиотек двумя способами. Во-первых, теперь все СОМ-компоненты должны были регистрироваться и, таким образом, могли быть загружены только из одного места. Во-вторых, когда СОМкомпоненты модифицируются для расширения их функциональности, они должны наряду с новыми интерфейсами поддерживать старые интерфейсы (для сохранения совместимости с предыдущими версиями). Но проблемы все еще возникали из-за того, что новые версии компонентов зачастую изменяли алгоритм работы программы, от которого зависели старые клиенты. В операционной системе Windows 2000 для решения проблемы вызова неверных библиотек реализована концепция совместного использования нескольких версий одного компонента (side-by-side deployment). Windows 2000 также защищает системные библио16
Глава 1. Среда .NET Framework
теки от перезаписи более старыми версиями. Появление технологии .NET Framework подняло совместное развертывание и управление версиями на новый уровень. В .NET Framework управляемый код развертывается в виде сборок {assemblies). Можно представить, что сборки являются аналогом библиотек динамической компоновки (DLL) или исполняемых (ЕХЕ) модулей Visual Basic, но фактически это значительно больше, чем простые DLL- или ЕХЕ-модули, которые, по существу, представляют собой двоичные файлы. В отличие от традиционных библиотек и исполняемых модулей, сборки могут распределяться между несколькими библиотеками. Такое распределение может применяться для разделения часто и редко используемых частей приложения. Подобная технология дает преимущество сетевым и Internet-приложениям, загружая редко используемые части приложения только тогда, когда в них возникает необходимость. В среде СОМ обращение к компонентам происходит через библиотеки типов, которые описывают реализуемые на уровне методов объекты и интерфейсы. Библиотеки типов создаются на языке определения интерфейсов IDL (Interface Definition Language), который очень напоминает такие языки, как С и C++. Одной из проблем СОМ-технологии является то, что DLL и исполняемые модули хранятся отдельно от описывающих их библиотек типов. Сборки, наоборот, описывают сами себя. Информация, которая содержится в сборке, сообщает другим компонентам и среде CLR (Common Language Runtime) о функциональных возможностях сборки и о том, в каком контексте эта функциональность доступна. Сборки предоставляет вызывающим компонентам следующую информацию: •
версию;
•
обеспечение защиты доступа к коду (Code Access Security);
• облегчение межъязыковой интеграции. В .NET Framework существует два типа сборок: закрытые и общедоступные.
Закрытые сборки Сборки являются закрытыми по умолчанию. После инсталляции .NET Framework приложение может использовать только закрытые сборки, находящиеся в каталоге приложения или в одном из его подкаталогов. Это заметно отличается от того, что происходит в СОМ, где компоненты регистрируются в системе и широко доступны для всех приложений. Закрытые сборки частично устраняют проблему вызова не соответствующих приложению библиотек, так как два приложения могут использовать различные версии одного компонента, независимо от того, какая версия установлена на компьютере пользователя.
Общедоступные сборки Сборки совместного использования доступны для всех приложений данного компьютера. Когда какое-то приложение приступает к загрузке компонента, среда исполнения CLR пытается сначала использовать закрытую сборку, а общедоступную ищет только в том случае, если закрытая не найдена. Общедоступные сборки помещаются в глобальный кэш сборок (Global Assembly Cache— GAC). На рис. 1.2 показано окно расширенной оболочки Windows с примером содержимого GAC. Другие утилиты, поставляемые с .NET Framework, позволяют помещать компоненты в GAC, как это делает программа инсталляции Microsoft при установке .NET Framework. Сборки
17
-to! x! • i -
. *•-* Back
•
-"4
»
_tj
о
н-*
^ S e a r c h f-^iFoktefS
^j/r^story
j i^j"
X
-
1
j Address | _ J D:\WINNlAAssembly
(Type 1 Version 1,0.347.26100 Я _lJ WINNT j j i&Comlnterop i^ExcelServer 0.0.0.0 i - Q ackfcis Pre» 1.0.2204.21 ixjmscorlib S О Application СотрайЬЛу Scripts Pre» 1.0.2204.21 1 j j r C l AppPatch • ,,i яЬ System. Dravs*ig [ | Й C j Assembly lfisystem.W№orms PreJt 1.0.2204.21 I ] . ffl-Cj BBSTORE ! ! i |-C3 duster . 1 | j h-Cl Config I ; \ • ! г Q Connection Wi2ard ' !-Cj Crystal : .-Cj Cursors •• ffl C l Debug \ i^J Downloaded Program Files i ! Ш- О Driver Cache Fokfcrs
В большинстве случаев используются закрытые сборки, но компоненты сторонних поставщиков могут быть размещены в глобальном кэше. Одна из дополнительных возможностей глобального кэша — способность содержать несколько версий одной сборки, тем самым ликвидируя проблемы, связанные с установкой на компьютеры DLL разных версий, принадлежащих различным приложениям или их модификациям.
Метаданные В отличие от ранних разработок, архитекторы .NET Framework уверены, что весь код должен описывать себя сам, т.е. содержать информацию, которую могут использовать другие инструменты разработки программного обеспечения для определения правил взаимодействия с кодом. В .NET Framework это описание предоставляют метаданные {metadata). Метаданные играют ключевую роль как во время проектирования, так и во время исполнения сборки. Процесс исследования метаданных средой Visual Studio.NET и кодом разработчика называется отражением (reflection). Среда .NET Framework включает набор классов, облегчающих процесс отражения. Метаданные являются также ключом к пониманию того, как система безопасности .NET Framework контролирует использование типов в различных случаях. Этот вопрос более подробно рассматривается в главе 11, "Проектирование, архитектура и реализация приложений .NET Framework". Метаданные размещаются внутри сборки, в секции, называемой декларацией (manifest). Декларация содержит следующую информацию о сборке: • идентификатор; • список файлов; • связанные сборки и информация о версии;
18
•
экспортируемые типы;
•
объявления полей, методов, свойств и событий всех типов;
•
экспортируемые ресурсы;
•
запросы прав доступа. Глава 1. Среда .NET Framework
Наконец, метаданные облегчают уничтожение объектов. Среда .NET Framework использует метаданные для определения присущего каждому объекту способа его уничтожения: нужно ли удалить просто ссылку на объект или же его состояние следует предварительно сохранить и послать по сети с последующим восстановлением на другой стороне. C o m m o n
L a n g u a g e
R u n t i m e
В основе .NET Framework лежит пася управляющей среды (managed environment). Управляющая среда действует как распорядитель, контролирующий, какой код приложения исполняется в данный момент и что этому коду разрешено делать в системе. В управляющей среде разработчики освобождены от необходимости реализации всех низкоуровневых системных функций, обеспечивающих создание гибких, надежных и безопасных приложений. Среда исполнения в .NET Framework называется Common Language Runtime (CLR) и предоставляет все сервисы исполняющей среды для поддержки приложений .NET Framework. Хотя понятие "среда исполнения" хорошо знакомо разработчикам Visual Basic, CLR для .NET Framework кардинально отличается от традиционной среды исполнения Visual Basic. CLR отвечает за взаимодействие всего управляемого программного кода (managed code) с операционной системой. Программный код, который не поддерживает службы CLR, называется неуправляемым кодом (unmanaged code). В бизнес-приложениях неуправляемый код используется очень редко. Компилятор VB.NET создает только управляемый программный код. Некоторые другие компиляторы могут переключаться для генерации как управляемого, так и неуправляемого кода. Программный код, написанный на языке С#, является управляемым по умолчанию, но С# может также создавать и неуправляемый код. С другой стороны, код на языке Visual C++.NET по умолчанию не является управляемым, но компилятор может быть переключен для создания управляемого кода. JScript.NET, подобно VB.NET, создает только управляемый программный код. CLR отвечает за выполнение следующих задач: •
поддержка универсальной системы типов (Common Type System);
•
сборка мусора (Garbage collection);
• управление компиляцией по требованию (Just-In-Time compilation); •
управление версиями (Versioning);
• обеспечение безопасности (Security). Универсальная система типов более подробно рассматривается в главе 9, "Обработка ошибок". Система сборки мусора и безопасность описываются в главе 10, "ADO.NET". Остальные задачи CLR обсуждаются далее в этой главе.
Компиляция по требованию В большинстве традиционных сред разработки программного обеспечения разработчики компилируют код перед исполнением программы. С появлением байт-кода Java процесс компиляции можно было откладывать до момента его исполнения, что позволяло создавать приложения, одинаково функционирующие на нескольких платформах, без создания нескольких инсталляционных пакетов. Технология .NET Framework, развивая эту концепцию, продвинулась далее: развертывание приложений, управление версиями и поддержка сценариев безопасности на основе так называемой компиляции по требованию (Just-In-Time compilation). Когда сборка компиCommon Language Runtime
19
лируется в среде Visual Studio.NET, она преобразуется в специальный промежуточный язык Intermediate Language (IL). Это кроссплатформенная версия машинного языка. После того как программа скомпилирована в IL, она может быть преобразована в "родной" машинный код с помощью компилятора ЛТ. Код компилируется во время исполнения программы. Когда кокой-то код вызывается для исполнения, CLR вначале проверяет, была ли вызываемая функция уже скомпилирована и помещена в программный кэш. Если код в кэше не найден, то CLR совместно с компилятором проверяет метаданные, чтобы определить, относится ли этот код к безопасному типу. Код безопасного типа (type-safe) — это код, который обращается только к разрешенным областям памяти. Это гарантирует, что объекты изолированы друг от друга и не могут умышленно или неумышленно делать небезопасные для системы операции. После проверки CLR может принять вызов кода при следующих условиях: •
ссылки на типы строго совместимы с объявленными типами;
•
для объекта вызываются только присущие ему операции;
• идентификаторы совпадают с заявленными. В среде .NET Framework реализована очень надежная и богатая возможностями компилирующая модель. Она предлагает несколько вариантов компиляции кода, предоставляя несколько версий компиляторов. Среда .NET Framework поставляется с двумя компиляторами: обычным и экономичным. Обычный компилятор преобразует IL-код в "родной" машинный код во время его исполнения подобно тому, как работают компиляторы в традиционных средах разработки. Экономичный компилятор спроектирован для вычислительных устройств с небольшим объемом памяти и относительно малопроизводительным центральным процессором. К таким устройствам можно отнести разнообразные КПК и сотовые телефоны. Экономичный компилятор отслеживает код, и, когда ресурсов становится недостаточно, старый скомпилированный код, который ни разу не исполнялся, удаляется. Это значит, что IL-код придется компилировать заново в случае, если он будет вызван после удаления из памяти. Microsoft разработала также прекомпилятор (Pre-JIT compiler), который позволяет транслировать сборку целиком перед ее запуском. При этом исполненный один раз код работает намного быстрее. Однако IL-код по-прежнему должен устанавливаться вместе с приложением для того, чтобы среда исполнения CLR могла выполнить ве рификацию кода. В .NET Framework решена проблема блокировки файлов во время использования сборок компилятором. Поскольку исполняемый код помещается в кэш, файлы не блокируются. В случае с ASP.NET, если сборка изменяется, то CLR автоматически запускает новый процесс и переадресует все новые запросы уже к этому процессу. Все существующие в текущем процессе запросы будут отработаны, после чего процесс уничтожается.
Управление версиями В .NET Framework контроль версий имеет гораздо большее значение, чем простое документирование. Теперь номер версии является частью модели распространения и исполнения. Каждой сборке присваивается номер версии, состоящий из четырех частей (рис. 1.3). Major ; Minor ; Build
2
.
О
.
2
Revision
.
11
Рис. 1.3. Номер версии
20
Глава 1. Среда .NET Framework
Когда компилятор генерирует сборку, он записывает в свою декларацию версии других используемых ею сборок. После установки приложение старается использовать сборки только тех версий, которые согласуются с политикой контроля версий (version policy). Для среды .NET Framework характерна политика контроля версий по умолчанию, которая может быть переопределена. Политика контроля версий по умолчанию указывает, что загружаемая сборка должна иметь одинаковые минимальный и максимальный номера версий и ищет самые большие номера создания сборки и ревизии. Политика контроля версий по умолчанию предполагает следующее: •
сборки с различными старшими номерами версии несовместимы;
•
сборки с различными младшими номерами версии обычно не совместимы;
•
сборки с различными номерами создания сборки обычно совместимы;
• сборки с различными номерами ревизии обычно совместимы. В .NET Framework контроль версий можно усилить, используя политику контроля версий по умолчанию или настраиваемую политику, хранящуюся в конфигурационном файле. В настраиваемой политике контроля версий конфигурационный файл служит для определения используемой версии компонента. Для исполняемых программ политика контроля версий хранится в файле с именем, аналогичным названию файла приложения, и отличается только расширением файла: . c o n f i g вместо . е х е . Например, приложению с названием M y A p p l i c a t i o n . e x e соответствует конфигурационный файл, называемый M y A p p l i c a t i o n . c o n f i g . В листинге 1.1 приведен код конфигурационного файла. Этот файл сообщает CLR, что вместо сборки DataBaseAccess версии 1.0.0.0 можно использовать сборку Data Base Access версии 2.0.0.0. ЛИСТИНГ 1.1. Пример конфигурационного файла приложения
Пространства имен Прежде чем рассматривать типы проектов, доступных в VB.NET, важно понять концепцию пространства имен. Пространство имен используется для организации компонентов в группы по логическому принципу. В модели компонентных объектов СОМ есть два уровня: имя компонента и имя класса. В .NET можно иметь гораздо больше уровней. Например, для применения сериализации в .NET используется пространство System. XML. S e r i a l i z a t i o n . Это пространство имен содержит различные классы для организации XML-сериализации (Extensible Markup Language — расширяемый язык разметки). Среда .NET Framework использует пространство имен для уменьшения беспорядка в коде и устранения неопределенности при разрешении вызовов. Пространства имен
21
В СОМ-приложениях для связки и организации компонентов применяется 128разрядный глобально уникальный идентификатор GUID (Global Unique Identifier). Поэтому удобные в использовании имена в СОМ-приложениях ограничены названиями библиотек и классов, например: MyApplicationComponent.DtaBaseAccess В .NET Framework глобально уникальные идентификаторы GUID заменены пространством имен. Пространство имен, снимая ограничение СОМ-технологии на количество уровней, позволяет организовать компоненты более логично. В .NET Framework компоненты собираются в пространство имен. После присвоения этому пространству 128-разрядного хэш-ключа, создаваемого с помощью утилиты Shared Name, гарантируется, что никакой другой одноименный компонент не создаст путаницы в системе. Процесс хэширования известен как процесс создания уникального имени (в терминологии Microsoft — "строгого" имени), которое исключает возможность использования неверного компонента даже в случае, если этот компонент имеет идентичное пространство имен и название класса. Строгие имена не требуются для закрытых сборок, но обязательны для общедоступных. Как можно видеть из следующего примера, синтаксис определения пространства имен очень прост: Namespace NamespaceName End Namespace А вот как выглядит формат имен: NamePartl.NamePart2.NamePart3:.. NamePartX Microsoft предлагает в качестве первой части имени использовать название организации, создающей компонент, а в качестве второй — названия технологий, таких как XML, Data или Windows. Одинаковое пространство имен может использоваться в нескольких файлах проектов. В этом случае все классы компилируются в одно адресное пространство. Это облегчает разработку программного обеспечения несколькими пользователями. Кроме этого, становится возможным создание иерархических структур, когда одно пространство имен является частью другого, как показано в листинге 1.2. Листинг 1.2. Пример использования пространства имен Namespace Empowered.VisualBasicDotNetForDevelopers.Samples Public Class Employee ' Код класса Employee End Class Public Class Department 'Код класса Department End Class Namespace Payroll Public Class PayCheck 'Код класса PayCheck End Class Public Class TimeSheet 'Код класса TimeSheet End Class End Namespace End Namespace
Обратите внимание на то, что в листинге 1.2 имя NamePartl яаняется корневым пространством имен. По умолчанию Visual Basic.NET в качестве корневого имени использует название проекта. Для изменения корневого имени откройте диалоговое окно свойств проекта и измените свойство Root namespace, как показано на рис 1.4. 22
Глава 1. Среда .NET Framework
Common Properte is Assembyl name: v General Namespaces Verston Qutputtype: Bud l Imports Ca lss Lb i rary Reference Path R o o t n a m espace Sharn ig Namespaces Desg i ner Defautls ~"1 Confg i urato i n Properte is
Hdp Рис. 1.4. Свойства проекта При глубоко вложенных именах команды создания объектов классов могут иметь большую длину, что неудобно при вводе кода программы. Случай длинной цепочки пространств имен демонстрирует пример определения классов Department и TimeSeet: Dim oDepartment as Empowered.VisualBasicDotNetForDevelopers.Samples.Department Dim oTimeSheet as Empowered.VisualBasicDotNetForDevelopers.Samples.Payroll.TimeSheet Во избежание ввода длинных цепочек пространств имен в VB.NET применяется ключевое слово Import. С помощью команды Import можно импортировать имена, на которые ссылается данный проект. Обратите внимание, что команды импортирования пространства имен должны помещаться в начале кода. В листинге 1.3 демонстрируется использование команды Import. ЛИСТИНГ 1.3. Использование команды import
Import Empowered.VisualBasicDotNetForDevelopers.Samples Import Empowered.VisualBasicDotNetForDevelopers.HumanResources.Payroll Public Class TestClass Private oDepartment as Department Private oTimeSheet as TimeSheet End Class Этот подход облегчает ввод и делает код более удобочитаемым.
Библиотека классов .NET Framework Среда .NET Framework предоставляет разработчикам большую и разнообразную библиотеку классов. Повторное использование и расширение стандартных классов позволяет быстрее создавать надежные приложения с широкими возможностями, так как новая библиотека классов предоставляет множество функций, которые ранее программистам приходилось реализовать самостоятельно.
Библиотека классов .NET Framework
23
На самом верхнем уровне библиотеки классов находится пространство имен System, которое является корневым для всех классов .NET Framework и содержит все основные типы данных, используемые разработчиками для создания приложений. В табл. 1.1 приведено краткое описание функций пространств имен .NET Framework верхнего уровня. Таблица 1.1. Функции библиотеки классов .NETFramework Сервис
Пространство имен
Ядро .NET Framework Работа с данными Работа с XML Компонентная модель
System System.Data
Конфигурация Службы Framework
Поддержка национальных календарей, алфавитов и т.п. Сеть и Internet Поддержка хэш-таблиц, очередей, стеков, списков и т. п. Работа с файлами и каталогами Работа с текстом и поиск в нем Поддержка потоков, блокировок (locks), заглушек (mutexes), мониторов Исследование метаданных сборок и получение свойств находящихся в них методов и классов Рисование Построение графического интерфейса пользователя (GUI) Классы для взаимодействия с СОМ Доступ к объектам в других процессах и на других компьютерах Сериализация управляемых компонентов Шифрование и управление правами доступа к коду ASP.NET
Развертывание приложений Одна из целей проектирования .NET Framework состояла и том, чтобы сделать развертывание приложений таким же простым, как копирование файлов. Этот способ используется при инсталляции Web-приложений ASP (Active Server Pages) и статически связанных исполняемых модулей.
24
Глава 1. Среда .NET Framework
СОМ-приложения и компоненты требуют регистрации в системном реестре Windows. К тому же, если компонент используется, инсталляция его новой версии невозможна. При развертывании приложений в .NET Framework не возникает коллизий между разными версиями одинаковых библиотек и приложения устанавливаются простым копированием файлов. Инсталляция новых приложений не оказывает никакого влияния на существующие программы. Приложения очень просто переустанавливаются даже в том случае, если существующие компоненты уже используются. Фактически приложение может использовать несколько версий одного компонента. Все приложения .NET поставляются с описывающими их метаданными и потому не требуют регистрации в системном реестре. Если же компонент .NET будет вызываться из СОМ-приложений, то такая регистрация требуется. Приложения .NET поддерживают несколько сценариев инсталляции. Наиболее общим является простое копирование файлов приложения в нужный каталог — так называемое развертывание командой XCOPY. При использовании простого копирования CLR для поиска и загрузки закрытых сборок просматривает каталог и подкаталоги данного приложения.
Резюме Среда .NET Framework — это комплексная и очень надежная платформа для построения традиционных Windows-приложений и Internet-ориентированных систем. Microsoft потратила много времени и усилий для создания самой устойчивой платформы разработки. В .NET Framework компания Microsoft отошла от используемой в прошлом "собственнической" модели бизнеса. Технология .NET Framework основана на отраслевых стандартах. Она допускает кроссплатформенное исполнение и взаимодействие. Разработчики должны научиться правильно использовать новую платформу для решения своих задач. При этом важно не просто изучить языки программирования, но и научиться эффективно применять возможности данной технологии. В этой главе кратко описаны основные возможности .NET Framework. Материал последующих глав призван помочь вам глубже изучить эти возможности для создания эффективных приложений, способных решить ваши задачи.
Резюме
25
V i s u a l
S t u d i o . N E T
Компания Microsoft всегда занимала ведущие позиции в области разработки инструментальных средств, и программисты Visual Basic зачастую первыми испытывали ее инновации. Например, качественно новая система IntelliSense, позволившая разработчикам просматривать списки доступных свойств и методов объекта, впервые появилась в Visual Basic 5. Разработка среды Visual Studio.NET пополнила список инноваций Microsoft.
Введение в Visual Studio.NET Visual Studio.NET— это среда разработки программного обеспечения, поддерживающая практически любой язык программирования. Подобное утверждение может вызвать замешательство среди программистов, привыкших к работе с определенным языком или средой разработки. Среда Visual Basic 5 была прототипом модели интегрированной среды разработки (Integrated Development Environment— IDE) для всего набора программ, входивших тогда в Visual Studio, но по непонятным причинам следующая версия (Visual Basic 6 в пакете Visual Studio 6) не унаследовала эту модель. Интегрированная среда разработки Visual Basic 6 содержала инструменты управления проектами и проектными группами, а редактор включал расширенную поддержку IntelliSense. Но инструменты работы с базами данных не поддерживали расширений, и часто для задач управления базами данных необходимо было обращаться к средствам Visual Studio 6. При первом запуске Visual Studio.NET появляется DHTML-страница, показанная на рис. 2.1; она содержит следующие ссылки: недавно используемые проекты, открытие существующего проекта, создание нового проекта, список обнаруженных в пакете ошибок, интерактивная библиотека MSDN, поиск по MSDN, группы новостей Microsoft и индивидуальная настройка среды разработки.
V5 Home Page I
Get Started
Get started on a recent, existing or new project: File Name Date Modified Ш VBITSZOOlbindma
Online Community
•5 VBrrs;DniBihdinasHf|ner ШлЦХфМй
Search Online My Profile
,•„>
Today, at 5:45 AM Monday, January IS, 20014:50:16 PM Friday, March 09, 2001 3:24:09 PM
'•••
% UseADOFl-omOotNet
Thursday, March 08, 200118:411:22 PM
Open Existing Project Log a Visual Studio.NfcT buo report W Show the start page on next startup,
........ , ... ,
Рис. 2.1. Начальная страница Visual Studio При щелчке на ссылке My Profile открывается страница с настройками среды разработки. На рис. 2.2 показано окно настройки среды с выбранным из раскрывающегося списка Profile профилем разработчика Visual Basic. После создания нового Windows-приложения новая среда разработки, подобно среде Visual Basic 6, открывает в дизайнере новую форму. Первым отличием, которое сразу можно заметить, является измененная панель инструментов (рис. 2.3). VBDoiNetForDcvelopertTimcReporting - Microsoft visual ВайсЛЕТ [design] - *s Home Наде, Ete
В VS.NET появилось новое свойство, называемое динамической справкой (Dynamic Help). Это система, которая автоматически формирует контекстно-зависимую справку. Формируемая справка отображается в специальном окне и содержит ссылки на разделы справочной системы. Список ссылок соответствует выполняемой в данный момент операции и динамически изменяется в процессе работы над проектом. На рис. 2.4 показано содержимое окна Dynamic Help при активном дизайнере форм. На рис. 2.5 показано содержимое окна Dynamic Help при активном редакторе кода. Средство просмотра проектов Project Explorer из Visual Basic 6 заменено в VB.NET новым окном Solution Explorer. В дополнение к возможностям Project Explorer в Solution Explorer добавлены новые функции. Например, ссылки на входящие в проект компоненты размещаются непосредственно в окне Solution Explorer, а не в отдельном диалоговом окне, как в Visual Basic 6. Web-ссылки также помещаются в окно Solution Explorer. На рис. 2.6 показано окно Solution Explorer с тремя проектами. В VB.NET добавлена возможность просмотра классов проекта и всех содержащихся в классе свойств, методов и интерфейсов. Ранее эта возможность была доступна только в Visual C++ и Visual J + + . На рис. 2.7 показано окно просмотра классов Class View. Впервые в VB.NET появилось окно Server Explorer, которое пришло на смену инструментам работы с данными из Visual InterDev 6. Используя это окно, можно проектировать компоненты с помощью метода "перетащить и опустить". Инструмент Server Explorer может быть использован для управления не только базами данных, но и другими программными серверами.
Введение в Visual Studio.NET
29
SI •VinduwsApplicatioitf-MicrosoltVmMHiasicNtf [design] -H>rmI.vb[OeslgnJ' Efe
Ed*
yiew
Boject
J - J ' u - B l i
SuNd
Debug
tf
^ -
'
Forml.vblDeflgn]' | •
format
I«*
Vjndow
• •
1
t
Нф
• Debuo
"
*
!
i
;
#
"
•
'
'
•
.
?
* * '>
Г
i
>
u
-
)
t
*
j
8
f
J
C
i l
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
H
e
l
p
i
n
d
o
F
o
r
m
C
*
w
l
s
a
F
s
o
r
m
s
D
e
s
i
c
n
e
r
'
s
t
o
§
System.C6mpon''i"i"f'5 (lei 1-jiirnespa.f.e Imno^s Stei-em^n.' " Addin-i Controb to Windows Form?: Windows Forms LavoU ODtions Chantftw the Bofdars of Windows Forms 5ettina Gud Ootions n.ir ail V-'indows Forms Setting the Location o- Windows Forms Introduction to Windows Forms
CreettM Тгапямгег* Windows Forms WiCidowi Form Contrti^ bv Furictiwi Vlsuad Studio Wafltthrouoha Lanauaoa Chanoes in Visual Da^ic.rCT 7,0 Visual Studio Dccurriertation Start Pat»
:
^Samples
|
J
^ Propf r+ies
О D^-namic Heto I
[Ready
„.,. .
' ••;'
/Vc. 2.4. Содержимое окна Dynamic Help при активном дизайнере форм :. WindowsApplicaUonz - Microsoft Visual Basic.NET ИеЯап] - Rmnl.vb £te
E* J e »
Eroject
&*J
Eebug
loofc
Help
J • _1 • I» У UP * 4=1
4•X
'This c:a!f is required by the Win Form Designer. IrltlalizeComponent
! TCDO: Add any mids!i23bon ^fer frie initiaiizeComponentQ I! End Sub ]. Щ \ 'Fv.nr, overrides dispose to cean up It» ccrfponent ist ™ j« O.Brrides Pubit Sub DeposeO ' MyBa^e.Dispose i components.Dispose I i End Sub |
ф
Protected Sub Forml_CI(ct:OiyVal sender As Object, ByVal e A;:
;•
End Sub
L
Code and Тем Editor Ci-irllng Technimj^f: a n j PrciQrftrr;mirin Pryhr Visual audio Wefrthrn Mh? language Ch^tnq- n i n 1 c - t rjff.T; 7,0 Visual audio Dotunwrtatton Start Paoe J 4 Samples £nterpHsa samples
End Class j^J I
j Ready •
±f i Lr>19
C0I6
Puc. 2.5. Содержимое окна Dynamic Help при активном редакторе кода
I |p frr desg i ner Test, vb h • g] frmPa i yer.vb
•• • '• $< ф-
| р frmfiayerlD.vb JJ3 rrmPlayers.vb VBITSZOOlBndingjDetaAcceis (aJ References
Pa lyerDataAccess.asmx Pteyers.xsd ] VBn5200ainrJngsOataAcce5S.dsico
Й ' О Advance-dBindingE.i.arriple2 i Й * J AtthbuteSet i as -*S AttributeSets f
j£ ••*£ Bases and Implemented Interfaces - • * BeghEdtO : •--.• CancelEditO •-•EndEditO j ••#• OnPlayerChangedQ 1 3 Й AddressO As 5trlng • • seKString) ; • -0 getO As String Ё-BS" DateOfB«rth() A* Date ] I™ •<&• set(Date) i L -:,ф getQ As Date 1 S ES RrstNameO As String L+i E f IDQ As 5tring ф- tf LastNameO As String E: US' ParentO As AdvancedBindingEvampleZ, Players Ф Й? PhotoO As Drawing.Bitmap 1 HrMSi TitleO As String a * c^dtDateOf Birth j - 4 * c_dtPrevDateOfeirth |- а * c_oAttributeSets - ^ c^oParent - a *c_oPrioto ' - vj^ c_*Address . - g9 c_5Firstname
I
jj ij
}-g# c_slartName !•• £# c_sPrevAddiess ; Q * c_sPrevr7irstname ; jj*t* c_sPrevL*stMarne I jjj* c_sPrevTit)e ; ^ # с_5ТИе : * # GetAttributesSetC) As VBITSZOOlBmdir^sHdper.IAttributeSets »• GetAttributesSetCString) As VBIT5200iBndngsHelpef .IAttributeSet ! I S] - * J Mayers I Ш-OhxabHt № i g VBITS2001Binding H ^ § ¥EITS2001Bindirigs[>ataAccess ffi **Oobd Й *;* PlayerDetaAccess ! Ш " ^ f Bases and Implemented Interfaces $ • InitializeComponentO •••--• Save(5trffig,Strlng,Stflng, String, String)
^ StfuUon ExptOref | ^ 1 Ciass
с. 2.6. Окно Solution Explorer
c. 2.7. Окио C/ass View
Благодаря Server Explorer (рис. 2.8) можно перетащить хранимую процедуру, журнал событий или очередь сообщений в окно дизайнера форм, и дизайнер автоматически создаст код, необходимый для использования этого объекта. Если щелкнуть правой кнопкой мыши на узле Performance Counters Счетчики производительности в окне Server Explorer и из появившегося контекстного меню выбрать команду Create New Category, появится диалоговое окно Performance Counter Builder (рис. 2.9). На рис. 2.10 показано окно Server Explorer и дизайнер форм после открытия узла Performance Counters и перемещения его на форму.
Введение в Visual Studio.NET
31
• Defn i e a new category and the it) of counters you want t to contain, or ecWthe vau l es fc* anewiting category. Category name: , [Visual basic, net (or deveo l pers : :: Category descrp i to i n: ID Sampel Performance Counter
м в Data Connections • E g Servers ! •• Щ Щ red-leader S - ^ Crystal Services Щ till Event Logs Si - Щ Loaded Modules Ш *r!»i Management Data ffi - l i f Message Queues l£i- E3 Performance Counters ffi •• ПЗ Processes ф % Services ф • ft SQL Server Database* ffi Щ Web Services
Counter Ц buWet
|dit T l
-
Name: |Tm i e$neet Entry Type: :•. .;,.•: |NumbefOtlsmt32 CounJw desaptbne . j•.;•: : vn l cmbef of tm i e entre i s made
-
— r. -
d Dee l te [
17 Sinjte Inaonce '""" •'
/"toe. 2.<У. Окно Server Explorer
ЕЙе
•;
p-New Counter"
% Server Exptoref
1^p
-
• Specify Iho details for each count» you want the catego у (о contain, then cfckAdd
I Ш СЭ sqlserver: latches EL*- C 3 sqlserver:locks \ Ш - D sqlserver: memory manager ш О sqlserver:replication agents EtJ • S sqlserver:replication dlst. Eg.. ! 7 ^ salserverirepltcatton looreader ! Ш GD sqlserver:replication merge S3- F ^ salserver:repteation snapshot ( Ш ЕЗ sqlserver:sql statistics . $•- E 3 sqlserver:user settable | ijj- G3 system EB- O t c p ! ф- Е5 telephony ; ф- 0 3 terminal services ! Щ Q terminal services session ф О thread
_*J
* •
• j F T i a
I ^ J M I I I W N I i W
•
•
•>
~
.
.
.
xi .
.
.
x
Q
1
.
&
^
i
I
я «i S w i i
3- F"^ visual basic.net for developers S E 3 web service r~i ^ 1 й- L^J rrocesses Ш~ *^з Services ф fjp SQL Server Databases
; kezd/
j гпч PetlormanceCoynteri
j
^
" Ln57
СЫ6
C
h
9
Pttc. 2.70. Окно Server Explorer с открытым узлом Performance Counter
Распространенной операцией в бизнес-приложениях является добавление единицы к Performance Counter каждый раз, когда происходит щелчок на форме. Пример кода, реализующего описанную выше операцию, приведен на рис. 2.11. Этот пример содержит код, сгенерированный дизайнером при перемещении на форму элемента Performance Counter, и добавленный вручную метод Forml C l i c k . 32
ProtEcted Sub Forml_Click(ByVal sender As Object, ByV'al e As SystBm.EventArgs) PerfbrmanceCounterl.IncrementBy(l) End Sub •
..
V
'•'• • ' ' ' • . . . -
'
:
I
Ready
'INS:
Рис. 2.11. Код, сгенерированный при перемещении на форму элемента Performance Counter
Интегрированная среда разработки Visual Studio.NET При разработке среды Visual Studio.NET многие диалоговые окна были обновлены и функционально расширены. Разработчики высказывали пожелание улучшить инструмент построения меню Menu Editor. На рис. 2.12 и 2.13 показаны диалоговые окна Menu Editor в Visual Basic 6 и VB.NET соответственно. Cant*** \\^ Как видно из рис. 2.13, Menu Editor в VB.NET — Name; f"^" это удобный интерактивный инструмент. З ^ ^*: I (None) Также были внесены существенные измене- Indei: j NegotiatePostioo: jo- None ния в диалоговое окно References. На рис. 2.14 fc*HpContextH>: To Г Sheeted . F Enabled F »sble Г jMndowU приведено окно References в Visual Basic 6. Диалоговое окно References в Visual Basic 6 [rsert | Delete имело фиксированный размер. Поэтому зачастую было сложно определить, какой СОМобъект выбирается для ссылки, особенно если он имел длинное имя или находился глубоко в структуре каталогов. На рис. 2.15 показано новое, более удобное диалоговое окно Add References в VB.NET. Это окно имеет отдельные вкладки для ссылок на элементы .NET Framework, компоненты СОМ и другие проекты. Puc. 2.12. Окно Menu Editor в Visual Basic 6 10
Интегрированная среда разработки Visual Studio.NET
1
33
:
'» ArraySort - Microsoft Visual Basc i.NET tdesignj - Foml.vb tte Ed* Sew Proe j ct Bud l Debug Toos l Wnidow Hep l • g l v S ',& О в ! •!
;>
Л f«
•••-' -
•
:
<Р - С „:
^ J B l XI
, Debug
VS Home Pegs f orml.vfa [Design]* F
i:
Output Find R Peady
" '"."'
C-WM f rJ . .'Vn i rfow T**k l.«
! Ln 132 Co! 12 Ch 12
Puc. 2.13. Окно Menu Editor в VB.NET
References - PraiecU ijffl Vsiual Basci For Appc il ato i ns yj Vsi ual Basci runtm i e obe j cts and procedures i V VsiuaIl Basc i .obe j cts .andjyotedures *' £I3£d!r^7!7HHiHHHHBMMMHIflB j IA5 Helper COM Component 1,0 Type Library LI IA5 RADIUS Protocol 1.0 Type Library • :-) VideoSoft VSFIexGrid 7,0 (OLEDB/Unicode) \ } A Brstaik 5ei ver AIC Component to Convert an lncorr
Priority
П Active DS 115 Extension Dll ! J Active DSII5 Namespace Provider " .1 Active DS Type Library I ; Actrve Setup Control Library U ActiveMovie control type library Г ^ActiveX DLL to perform Migration of M5 ReDCtsltorv V
£ Automation
;
•
г
location; D:\WIWT\Syst«n32\stdole2.tb Language: Standard
Puc. 2.14. Диалоговое окно References в Visual Basic 6
Редактор кода Visual Studio.NET Разрабатывая приложения в Visual Studio.NET, программист большую часть времени работает в окне редактора кода. Редактор кода Visual Studio.NET существенно изменен по сравнению с предыдущими версиями.
34
Глава 2. Visual Studio.NET
Свертываемые блоки кода Одним из наиболее интересных свойств, появившихся в редакторе кода Visual Studio.NET, являются свертываемые блоки кода. Пиктограммы в виде небольшого квадратика слева в окне кода (рис. 2.16) обозначают блоки кода. Add Reference .NET FranewOfk | COM | Projects |
Component Name : 1 Verso i n jpath cscomprngd u.u.u.u D:\WN I NT\Mc irosoft.NET\Fra. CustomMarshae lrs 1.0.2204.21 DAWINNHMc irasoft.hE l T\Fra. IEHost 0.0.0.0 D:\WN I NT\Mc irosoft.MEHFra. In Memory Compelir 7.0.0.9030 D:\WN I NT\Mc irosoft.NET\Fra. S I ymWrapper 0.0.0.0 D:\WINNTM ic i rosoft.KET\Fra. JScrp i t Engn ie 7.0.0.9031 D:\WINNTM lc irosoft.NET\Fra. Ma i osoft. ComSer vc i es t.0.2204.21 D\iWINNT\Mkrosoft,NEHFra. Mc i rosoft. VsiuaBasci 1.0.0.0 D:\WN l NTM ia i osoft.NET\Fra. Mc i rosoft. VsiuaB l asfc .Compa.t.i 1.0,0.0 D:\WN I NT\Mc irosoFt.NET\Fra. Mc i rosoft.VsiuatC 7.0.9030.0 D:\WINNTM ic i rosoft, NEUFra. Mirrrwrlr • VKt WNJ Hii. dtl 1 n.??n4.1fi r):WTNyiTM l rirnw>ft NFT^Frft.. z. Selected Cowonentst Component Name :
I Type
• •
|
Cancel
Help
Puc. 2.15. Диалоговое окно Add References в VB.NET
VisuatStudfo - Microsoft VisualBosicNET [design] - Fonn1 ,vb Fie £d* Ve iw Projed Quad Debug loots frid i ot» 4 • x ; a
Start Page Fofrnl .vb [Design.]* Forml.vb* | »| |(Declarations) I^JForml (VisualS(udio) Public ciassForini Inherits Svstem.Windows.Formsform Windows Form DesiqnfT >-f4**> ,*и^.'< < ode )
|ф iRegiorT^AppScatfon Logic* |e Privattj Sub Forml_Load(ByVal sender As System.Object, i PerformanceCounterl.IncrementBy(l) | i End Sub H#End Region | L End Class
s System£ventArgs) Нл
>£] Output Tasklfal "Ready
j: Ln S8
Cd 1
Ch 1
Puc. 2.16. Свертываемые блоки кода
Редактор кода Visual Studio.NET
35
При щелчке на этих пиктограммах блок кода сворачивается или разворачивается. Среда Visual Studio.NET автоматически создает блоки кода для каждой процедуры и класса. Кроме этого, можно определить собственные свертываемые блоки кода с помощью команд редактора #Region и #End Region, как показано в листинге 2.1. Листинг 2.1. Использование команд #Region и #End Region #Region "Мой собственный блок кода" P r i v a t e Sub DoSomething() End Sub Private Sub DoSomethingElse() End Sub #End Region Когда блок кода, определенный с помощью команд #Region и #End Region, находится в свернутом состоянии, то в окне редактора отображается только строка текста из команды iRegion, а остальная часть кода скрыта. Таким образом, команды редактора #Region и #End Region позволяют лучше организовать код, группируя методы в соответствии с выполняемыми ими функциями. На рис. 2.17 показан тот же код, что и на рис. 2.16, но в свернутом состоянии. VisualSludio Microsoft Visual Basic.NET [Assign] - Fonni.vb* Edit Wew Erojert guid QcbuQ
look Window ЦФ
Я %, iL, « I да ф I i 2 1 A % % Forml.vb[Design]* Forml.vb* |
'JFornil (VisualStudio)
|H\(Dedaratloni)
Гв Public Class Forml Inherits System.Windows.Forms.Form
' i SP-hi
it м п i uii't
End'class""
Output
T a s k List
Ready
Puc. 2.17. Свернутый блок кода
Автоматическое форматирование и завершение ввода кода Другими замечательными свойствами Visual Studio.NET являются автоформатирование и автоматическое завершение ввода кода. Например, когда в редакторе кода вводится оператор If, то редактор Visual Studio.NET автоматически вставляет блоки E l s e 36
Глава 2. Visual Studio.NET
и End If и смещает вправо любой код, помещаемый между блоками I f n E l s e n между E l s e и End If. Редактор имеет еще несколько интересных свойств форматирования. •
Номера строк могут автоматически вставляться и пересчитываться по мере ввода кода.
•
Можно активизировать перенос слов, чтобы код не выступал за границу экрана.
•
Всплывающие подсказки доступны для любого элемента кода. Если с кодом поставляется документация в формате XML (эта документация доступна в VB.NET как расширение), то при помещении указателя мыши на какой-либо метод, появляется всплывающее окно с описанием этого метода.
Включение URL в код и комментарии Новым свойством редактора кода Visual Studio.NET является возможность добавления адреса URL в программный код и комментарии. Например, можно поместить ссылку на дополнительную справку для фрагмента кода непосредственно внутрь этого кода или же поместить в код ссылку на адрес электронной почты разработчика, щелкнув на которой можно отправить свои заметки автору. При переносе кода проектов Visual Basic 6 с помощью мастера переноса (VB 6 Migration Wizard) эти ссылки используются для указания местоположения более детального описания кода.
Другие редакторы С VB.NET поставляется несколько других редакторов, помогающих разработчикам в процессе создания приложений. К этим редакторам относятся: редактор каскадных листов стилей (Cascading Style Sheet), редактор XML, редактор XSL, редактор хранимых процедур и редактор HTML. Во всех этих редакторах реализована технология IntelliSense. Особенно интересны редакторы HTML и XML. Например, редактор HTML автоматически подстраивается к выбранной версии языка разметки, а редактор XML проверяет правильность вводимых данных на основе выбранной схемы.
Visual Basic и .NET Framework Visual Basic существует около десяти лет. За это время было выпущено шесть версий. Visual Basic развился из простого, в некоторой степени ограниченного средства быстрой разработки до мощного инструмента разработки современных приложений, который также превосходно подходит для создания СОМ-компонентов. Однако, несмотря на то что Visual Basic стал наиболее популярным средством разработки, он имеет репутацию "игрушечного" языка, не подходящего для реализации серьезных проектов. И хотя подобное утверждение никогда не соответствовало действительности, некоторые разработчики презрительно относятся к Visual Basic по ряду причин. •
Затруднительное использование функций Windows API.
• Неполная поддержка объектно-ориентированной модели. • Необходимость в промежуточной среде исполнения. В то же время в Visual Basic реализован ряд великолепных средств, которые изменили индустрию разработки программного обеспечения. Другие редакторы
37
•
Компонентно-ориентированная разработка приложений с применением элементов управления (VBX и их преемников ActiveX).
•
Модель быстрой разработки приложений.
•
Инструменты визуального проектирования.
• Событийное программирование. Создатели платформы .NET Framework взяли из Visual Basic лучшие свойства и, доработав их, сделали доступным для разработчиков программ на других языках. Многие конструкторские решения в Visual Studio.NET также эволюционировали из Visual Basic, например, цитируя Давида Мендлена (David Mendlen) из Microsoft, основная цель проектирования ASP.NET — сделать разработку Internet-приложений "такой же простой, как и создание программ с помощью Visual Basic".
Введение BVB.NET При создании среды .NET Framework компания Microsoft использовала новый язык программирования, называемый С#. Поэтому многие полагают, что для разработки в среде .NET лучше всего обратиться к С#. Но С# использован Microsoft просто потому, что он был первым языком, реализованным в .NET, и поэтому имеет наилучшую поддержку. Платформа .NET Framework может поддерживать практически все существующие языки программирования, и в первую очередь — Visual Basic. При создании Visual Basic.NET язык Visual Basic был полностью переписан. Все же, несмотря на многочисленные изменения, он сохранил большую часть привычного для программистов синтаксиса, и новые синтаксические дополнения следуют установленным в языке традициям. Visual Basic, в отличие от C/C++, никогда не был стандартизованным языком. Его синтаксис всегда контролировался компанией Microsoft, а развитие никогда не ограничивалось рамками стандартов. Отсутствие стандартов хорошо служило развитию Visual Basic в прошлом, но также позволяло Microsoft вносить в него изменения, которые могли нарушить работу приложений, созданных с помощью предыдущих версий языка. С появлением .NET Framework эта тенденция будет изменена, поскольку несоблюдение совместимости в последующих версиях VB.NET будет означать разрушение всей платформы .NET Framework. VB.NET поддерживает все возможности среды .NET. Более того, VB.NET — это основной инструмент разработки полностью управляемых приложений, использующих платформу .NET Framework.
Цели проектирования VB.NET Компания Microsoft постепенно уходит с рынка операционных систем в сторону рынка предоставления услуг через Internet. Эти услуги, известные как Web-службы, позволят разработчикам создавать "настоящие" распределенные приложения. Для обеспечения поддержки этой концепции задача проектирования VB.NET формулировалась приблизительно так: сделать для разработки Web-служб то же, что сделала первая версия Visual Basic для разработки Windows-приложений. Поэтому перед разработчиками VB.NET ставились следующие цели:
38
•
VB.NET должен быть узнаваемым разработчиками Visual Basic;
•
VB.NET должен иметь простой синтаксис;
•
VB.NET должен позволять использовать основные свойства .NET Framework;
•
Глаза 2. Visual Studio.NET
• •
VB.NET должен поддерживать многоязычную среду .NET Framework; VB.NET должен обеспечить перенос существующих приложений Visual Basic 6 в среду .NET Framework;
• VB.NET должен максимально сохранить синтаксис предыдущих версий Visual Basic. Перечисленные выше цели проектирования дают разработчикам VB.NET достаточный простор для создания языка, который позволит легко разрабатывать приложения .NET.
Доступность Visual Basic, как язык программирования, был всегда доступен широкому кругу разработчиков и потенциальных разработчиков. Разработчик на Visual Basic может быстро приступить к решению своих задач и повышать свое мастерство в процессе их решения. Доступность Visual Basic является одновременно и достоинством и недостатком. Дело в том, что Visual Basic вовлек в процесс создания программ массу людей, никогда ранее не занимавшихся разработкой программного обеспечения. Одни из них освоили и стали успешно использовать Visual Basic, в то время как другие потерпели неудачу. К сожалению, Visual Basic часто имеет плохие отзывы со стороны разработчиков, которые просто не смогли в достаточной для решения их задач мере освоить этот инструмент. Ключевое свойство, которое привлекало разработчиков и потенциальных разработчиков в Visual Basic, — это та простота, с которой можно было начать разработку приложений. Существует множество причин, по которым Visual Basic стал таким доступным. Основная причина заключается в том, что синтаксис Visual Basic не отпугивает людей. Даже начинающий программист может понимать код Visual Basic. Поэтому разработчикам гораздо легче освоить язык с таким привлекательным синтаксисом, чем традиционные языки, подобные C/C++. Visual Basic, подобно другим объектно-ориентированным языкам, скрывает реализацию функциональности программы от ее интерфейса. Известно, что одной из основных идей объектно-ориентированного программирования является инкапсуляция, которая означает, что нужно представлять то, что может быть сделано, и держать в секрете, как это в действительности реализовано. Например, объект "кнопка" имеет событие "щелчок мыши". В данном случае Visual Basic скрывает обработку сообщения и цикл сообщений Windows, обеспечивающие генерацию реального события. Таким образом, Visual Basic скрывает от разработчиков внутреннюю организацию программирования для Windows. (Разумеется, опытные программисты находят способы обойти многие из этих встроенных ограничений.) Другим ключевым свойством для начинающих является возможность нетипизированного программирования, т.е. возможно объявление переменных без определения хранящихся в них типов данных. Это, фактически, позволяет переменной хранить данные любого типа. Как правило, нетипизированное программирование использовать не рекомендуется, так как оно приводит к появлению в приложениях трудно обнаруживаемых ошибок. Однако такой способ объявления переменных позволяет программистам начать разработку без изучения типов данных и способов преобразования данных из одного типа в другой. Visual Basic — это язык программирования, который можно быстро изучить и приступить к разработке приложения. При этом очень важно рассмотреть не только основные возможности языка, но и изучить правильный способ решения таких задач, как доступ к базам данных, обработка строк, управление состоянием и ресурсами. Visual Basic базируется на простоте и узнаваемости. Если корректно писать программы на Visual Basic, то код получается практически самодокументируемым. Так, Visual Basic не Visual Basic и .NET Framework
39
предусматривает использования специальных символов и операторов вместо слов и команд, за исключением тех случаев, когда операторы являются особенно распространенными и простыми. Поэтому, используя Visual Basic, легко создать код, понятный другим разработчикам. Такие языки программирования, как C/C++ и производные от них Java и С#, в большей степени полагаются на комментирование кода. Комментирование кода является хорошим способом документирования программ, но, так как код в процессе тестирования часто модифицируется, а комментарии имеют тенденцию оставаться неизменными, возникает проблема несоответствия кода и документации. В случае же, когда код является самодокументируемым, документация остается актуальной и после внесения в код изменений. Некоторым разработчикам не нравится, что программирование на Visual Basic требует ввода большего объема кода по сравнению с другими языками при решении одинаковых задач. Это одна из причин, по которой многие разработчики C/C++ считают Visual Basic "игрушечным" языком, в то время как в действительности это свойство упрощает последующую поддержку программ, написанных на Visual Basic.
Поддержка объектно-ориентированного программирования Изначально Visual Basic был объектно-ориентированным языком программирования. В том смысле, что в Visual Basic всегда применялись объекты в виде элементов управления или других компонентов, используемых при разработке. Начиная с четвертой версии, объектно-ориентированные конструкции появились и в синтаксисе Visual Basic. В следующей версии, Visual Basic 5, были добавлены новые языковые конструкции, которые расширили поддержку объектно-ориентированного программирования. Но только в VB.NET появился механизм наследования с возможностью переопределения методов в производных классах. В дополнение к возможности наследовать классы, созданные в Visual Basic, среда VB.NET позволяет наследовать классы, написанные на любом .NETсовместимом языке, включая С#, JScript.NET и C++.NET, или на другом языке, реализованном для платформы .NET Framework компанией Microsoft либо другим производителем программного обеспечения. Наследование интерфейсов, все еще являющееся ключевым для создания гибких приложений, также расширено в VB.NET. Синтаксис описания наследования интерфейсов изменился, чтобы позволить одному методу реализовать несколько интерфейсов. В VB.NET добавлено несколько новых ключевых слов, которые помогают конструировать гибкие и мощные объекты. Эти ключевые слова позволяют контролировать, как именно методы могут быть переопределены и перегружены и как методы и свойства защищаются от несанкционированного доступа. С интеграцией Visual Basic в .NET Framework наконец-то появился объектноориентированный способ получения адресов функций через специальные представители — делегаты (delegates). Делегаты являют собой весьма элегантный способ синхронизации обратных вызовов, событий и других способов управления функциями. Со всеми этими изменениями VB.NET стал полнофункциональным объектноориентированным языком с простой и понятной моделью создания .NET-приложений. Несмотря на то что большая часть синтаксиса, поддерживающего процедурный стиль программирования предыдущих версий Visual Basic, все еще доступна в VB.NET, рекомендуется при создании новых приложений и преобразовании существующего кода не использовать процедурный синтаксис, а применять современный объектно-ориентированный стиль программирования.
40
Глава 2. Visual Studio.NET
Современные языковые конструкции Хотя Visual Basic.NET поддерживает старые способы обработки ошибок, в новую версию добавлена возможность структурной обработки ошибок. Новый способ значительно упрощает и делает прозрачной обработку ошибок. В VB.NET реализована идея атрибутивного программирования, которое является частью .NET Framework. Атрибутивное программирование позволяет разработчикам обращаться к свойствам методов для контроля взаимодействия другого кода с методами. Этой обработкой кода занимается среда исполнения.
Безопасность Технология .NET Framework привнесла в VB.NET завершенную инфраструктуру создания защищенных приложений. Безопасность в предыдущих версиях Visual Basic достигалась несколькими способами, включая создание специального пользовательского кода, использование встроенных средств безопасности Windows и применение средств COM/MTS и СОМ+. В VB.NET механизмы обеспечения безопасности встроены непосредственно в среду .NET Framework. При использовании системы безопасности .NET Security (встроенная система безопасности .NET Framework) можно достаточно просто защитить данные и процессы от несанкционированного доступа в приложениях VB.NET. В VB.NET добавлено новое свойство, обеспечивающее безопасность типов. До появления VB.NET среда исполнения кода Visual Basic при управлении данными пыталась конвертировать данные какого-либо типа в любой другой тип, доступный в языке. Это автоматическое преобразование, иногда называемое программистами "злоумышленным приведением типов", может существенно усложнить отладку кода. Сейчас в VB.NET по умолчанию требуется явное приведение типов. Установка явного приведения типов может быть отключена, но это целесообразно делать только в случае переноса приложений из предыдущих версий Visual Basic или же для приложений с поздним связыванием.
Многоязычная интеграция Созданные в VB.NET классы полностью открыты к расширению и способны расширять классы, реализованные на других языках. Это значит, что классы VB.NET могут быть использованы как базовые в других языках, а также могут использовать и наследовать классы, созданные на других языках. Это позволяет разработчикам при решении специфических задач выбирать наиболее подходящий язык программирования. Так, если задача выполняет большое количество вычислений, то лучшим выбором будет язык, ориентированный на математическую обработку данных. Если же требуется интенсивная обработка строковых данных, то, естественно, лучше использовать наиболее подходящий язык для решения подобных задач.
Взаимодействие с СОМ и Windows API Компоненты VB.NET могут вызывать и использовать СОМ-компоненты. В свою очередь, СОМ-компоненты и приложения могут использовать компоненты, созданные в VB.NET. Доступ к Windows API реализован в .NET Framework с помощью встроенных классов и через знакомый разработчикам VB метод plnvoke. Хотя среда .NET Framework поддерживает различные платформы, эта технология позволяет при необходимости получить прямой доступ к самой платформе. Возможность прямого доступа к компьютерной платформе существенно отличает технологию Java от .NET Framework. Взаимодействие различных компонентов более подробно описывается в главе 12, " Взаимодействие элементов языка". Visual Basic и .NET Framework
41
Резюме Visual Studio.NET можно с уверенностью назвать наиболее значительной разработкой компании Microsoft, и вполне возможно, что эта среда является наилучшим инструментом, когда-либо созданным тем или иным производителем программного обеспечения. Программисты, имеющие опыт работы с предыдущими версиями Visual Basic, найдут новый инструмент очень удобным в использовании. Те, кто работал с Visual InterDev, также найдут новую среду разработки приложений очень знакомой. Среду Visual Studio.NET можно рассматривать как первое приложение платформы .NET Framework, так как значительная ее часть была действительно создана с использованием технологии .NET Framework.
42
Глава 2. Visual Studio.NET
Концепции объектноориентированного программирования За время своего существования Visual Basic превратился из объектного {object-based) в объектно-ориентированное (object-oriented) средство разработки. В ранних версиях Visual Basic некоторые ключевые особенности языка не были реализованы. Предыдущие версии Visual Basic позволяли программистам создавать классы и использовать их при разработке приложений. При этом основные возможности объектно-ориентированного программирования практически не учитывались. Это не мешало разработчикам создавать надежные системы, формируемые на компонентной основе, однако препятствовало созданию расширяемых конструкций. К Visual Basic.NET это не относится. Объектно-ориентированное программирование в .NET Framework фактически является необходимым условием, поэтому Visual Basic превратился в многофункциональный объектно-ориентированный язык. Новыми свойствами языка являются поддержка наследования, новые методы объявления объектов, а также возможности атрибутивного программирования. Кроме этого, в Visual Basic.NET значительно улучшена поддержка интерфейсов, свойств и событий. Объектно-ориентированное программирование имеет особое значение для создания сложных приложений. Например, в предыдущих версиях Visual Basic далеко не многие стремились к использованию объектно-ориентированных методов программирования. Подобную ошибку не следует повторять в VB.NET. Для эффективной работы в среде VB.NET разработчик должен понимать и правильно использовать ключевые концепции объектно-ориентированного программирования. Существует четыре основных понятия, относящихся к объектно-ориентированной среде разработки: абстрагирование, инкапсуляция, полиморфизм и наследование. В этой главе остановимся на каждом из них.
Абстрагирование в Visual Basic.NET Абстрагирование (abstraction) — это возможность обобщения представлений объекта в виде типа данных, имеющего определенный набор характеристик и способного выполнить какой-либо набор действий. Например, абстрагирование объекта "собака" содержит характеристики c o l o r (цвет), h e i g h t (рост) и w e i g h t (вес), а также набор действий, таких как run (бежать) и b i t e (кусать). В данном случае характеристики собаки называются свойствами {properties), а действия — методами (methods). В объектно-ориентированных языках абстрагирование обеспечивается посредством классов (classes). Классы определяют свойства и методы объекта, но старайтесь не забывать о том, что разработчик не может использовать класс непосредственно; напротив, объект должен быть создан из класса — он должен быть реализован (instantiated). В Visual Basic поддержка классов существует начиная с версии 4.0. Вплоть до появления VB.NET каждый класс был выполнен в виде отдельного файла, абстрагирующего данный объект. Примеры классов Visual Basic 6.0 и Visual Basic.NET приведены в листингах 3.1 и 3.2. В Visual Basic 6.0 класс определяется в виде файла с расширением . CLS. В языке VB.NET способ определения классов изменился — эта операция выполняется непосредственно с помощью кода. В примере, который приведен в листинге 3.2, обратите внимание на операторы P u b l i c C l a s s Car и End-Class. ЛИСТИНГ 3.1. Класс Visual Basic 6.0
Public MaximumSpeed as Integer Public ModelName as String Public Sub Accelerate() 'Код для начала движения автомобиля End Sub Public Sub StopO 'Код для остановки автомобиля End Sub ЛИСТИНГ 3.2. Класс VB.NET Public Class Car Public MaximumSpeed as Integer Public ModelName as String Public Sub Accelerate() 'Код для начала движения автомобиля End Sub Public Sub StopO 'Код для остановки автомобиля End Sub End Class В этих листингах приведен пример абстрагирования достаточно простого объекта — автомобиля. Для того чтобы воспользоваться этой абстракцией, необходимо в первую очередь создать экземпляр класса. В Visual Basic 6.0 есть несколько различных способов создания классов. В VB.NET это положение изменилось. Наиболее распространенным методом создания объекта является использование ключевого слова New. В листинге 3.3 приведены три метода создания экземпляра класса в Visual Basic 6.0, а в листинге 3.4 — четыре метода выполнения подобных операций в VB.NET. ЛИСТИНГ 3.3. Три метода создания экземпляра класса в Visual Basic 6.0
Dim oCar as New Car Set oCar = New Car Set oCar = CreateObject("Vehicles.Car") 44
Глава З. Концепции объектно-ориентированного программирования
Обратите внимание на то, что метод CreateOb j e c t в листинге 3.4 не используется. Применение этого метода ограничено только созданием классических СОМкомпонентов и не распространяется на экземпляры компонентов .NET Framework. Вместо CreateOb j e c t с успехом используется метод System. A c t i v a t o r . C r e a t e l n s t a n c e . (Методу A s s e m b l y . C r e a t e l n s t a n c e соответствует System. A c t i v a t o r .CreateInstance.) Листинг 3.4. Четыре метода создания экземпляра класса в VB.NET Dim oCar as New Car oCar = New Car oCar = Assembly.Createlnstance("Car") oCar = System.Activator.Createlnstance("Car","URIToAssembly")
Инкапсуляция B V B . N E T Объект должен скрывать детали своей реализации, открывая "внешнему миру" лишь методы и свойства. Инкапсуляция (encapsulation) представляет собой доступность свойств и методов объекта," в то время как сам объект фактически скрыт от внешнего мира. Другими словами, объект подобен "черному ящику", т.е. те разработчики, которые с ним работают, могут даже не знать о том, что в действительности происходит внутри данного объекта. Инкапсуляция позволяет разработчикам создавать объекты, которые могут быть изменены без какого-либо воздействия на использующий их клиентский код. Самое главное в том, что интерфейс (interface) объекта, т.е. набор его доступных свойств и методов, не меняется даже при изменении внутренней реализации объекта. Visual Basic поддерживает инкапсуляцию начиная с версии 4.0. Рассмотрим два простых примера. В листингах 3.5 и 3.6 представлены две реализации класса Person, выполненные двумя различными способами. ЛИСТИНГ 3.5. Первый способ реализации класса Person
Public Class Person Private m_sFirstName as String Private m_sLastName as String Public Property FirstNamef) as String Get FirstName = m_sFirstName End Get Set(ByVal Value as String) m_sFirstName = Value End Set End Property Public Property LastNameO as String Get LastName = m_sLastName End Get Set(ByVal Value as String) m_sLastName = Value End Set End Property Readonly Property FullNameO as String Get FullName = m_sLastName & ", " & m_sFirstName End Get End Property End Class
Инкапсуляция BVB.NET
45
Листинг 3.6. Второй способ реализации класса Person Public Class Person Private m_sFirstName as String Private m_sLastName as String Private m_sFullName as String Public Property FirstName() as String Get FirstName = m_sFirstName End Get Set (ByVal Value as String) m_sFirstName = Value m_sFullName = m_sLastName & ", " S m_sFirstName End~Set End Property Public Property LastNameO as String Get LastName = m_sLastName End Get Set(ByVal Value as String) m_sLastName = Value m_sFullName = m_sLastName & ", " & m_sFirstName End Set End Property Readonly Property FullNameO as String Get FullName = m_sFirstName End Get End Property End Class Приведенные примеры иллюстрируют инкапсуляцию процессов внутри класса. Несмотря на различия во внутренней реализации классов, внешний интерфейс не изменяется. Именно это и является целью инкапсуляции: позволить разработчику прозрачно использовать различные реализации одного и того же объекта.
ПолиморфизмвVB.NET Сущность полиморфизма (polymorphism) заключается в том, что разные объекты могут иметь различные реализации одной и той же характеристики. В качестве примера рассмотрим два объекта, один из которых является автомобилем Porsche 911, а Другой — Toyota Corolla. Оба объекта — автомобили; т.е. оба происходят из класса Саг и содержат метод d r i v e . Но реализации методов, как видите, могут разительно отличаться друг от друга. Судя по описанию, полиморфизм подобен инкапсуляции, но в то же время имеет некоторые существенные отличия. Инкапсуляция выражается в сокрытии внутренней реализации объекта. Полиморфизм, в свою очередь, проявляется в том, что различные классы могут иметь один и тот же интерфейс. В Visual Basic 4.0 была реализована достаточно ограниченная поддержка полиморфизма, осуществленная с помощью динамического связывания. Динамическое или позднее связывание (late binding) представляет собой определенную технологию, позволяющую определять во время выполнения кода, какие свойства и методы обеспечивает данный объект. При этом код может создавать какой-либо объект и вызывать его методы или свойства независимо от того, поддерживается ли объектом вызываемый метод во время компиляции. Если использовать два различных класса с одинаковыми свойствами и 46
Глава 3. Концепции объектно-ориентированного программирования
методами, то создавать отдельные экземпляры этого класса можно с помощью переменной типа o b j e c t . К сожалению, динамическое связывание не позволяет должным образом обеспечить безопасность типов во время компиляции. Концепция безопасности типов (type safety) гарантирует использование типов данных, соответствующих своему названию, например строковых для строк и т.д. При отсутствии механизма безопасности типов значительно возрастает количество потенциальных ошибок, возникающих при выполнении программы до завершения ее компиляции. Кроме этого, безопасность типов позволяет предотвратить взлом программ, используя некорректный фрагмент кода. В Visual Basic 5.0 появилась дополнительная форма полиморфизма, позволяющая использовать интерфейсы. Интерфейс (interface) определяет набор свойств, методов и событий, реализуемых данным классом. Один и тот же интерфейс может быть реализован одновременно несколькими классами. Переменная, определяющая значение интерфейса, может ссылаться на любой класс, реализующий данный интерфейс. Интерфейсы обеспечивают раннее связывание с объектом, что позволяет значительно повысить эффективность, а также обеспечить защиту типов во время компиляции. Интерфейсы являются одной из наиболее важных особенностей Visual Basic 5.0, правда, все еще наименее изученной и мало используемой. В VB.NET существенно улучшена поддержка интерфейсов. В настоящее время язык имеет прямую поддержку создания интерфейсов, что в более ранних версиях осуществлялось либо с помощью языка описания интерфейсов (IDL), либо путем создания пустых классов. Кроме того, какой-либо один метод может быть реализацией методов сразу нескольких интерфейсов. В листинге 3.7 приведен пример полиморфизма, реализованного с помощью динамического (или позднего) связывания, а в листинге 3.8 — с помощью раннего связывания. В том и другом примере показаны классы, реализующие методы Ride. Как видите, в обоих случаях метод может вызывать метод любого класса независимо от того, каким из объектов он используется. Именно в этом и состоит сущность полиморфизма: возможность создания кода, который использует различные объекты, реализующие один и тот же интерфейс. ЛИСТИНГ 3.7. Полиморфизм, реализованный с помощью позднего связывания
Public Class RollerCoaster Public Sub Ride() Console.WriteLine("Here we go") Console.WriteLine("Click, Click ,Click") Console .WriteLine ("Oh, *&@%") Console.WriteLine ( "That was great") End Sub End Class Public Class MerryGoRound Public Sub RideO Console.WriteLine("OK will go on it") Console.Writeline("Nap Time") Console.WriteLine("Yea its over") End Sub End Class Приведенный ниже код расположен в программе. Private Sub DayAtTheAmusementPark() Dim oRollerCoaster as New RollerCoaster Dim oMerryGoRound as New MerryGoRound Call GoOnRide(oRollerCoaster) Call GoOnRide(oMerryGoRound) End Sub
Полиморфизм в VB.NET
47
Private Sub GoOnRide(oRide as Object) oRide.RideO End Sub В данном случае предпочтительнее использовать раннее связывание, так как оно способствует повышению эффективности и позволяет находить ошибки, возникающие во время компиляции. Раннее связывание может быть реализовано с помощью интерфейсов, как показано в листинге 3.8. Листинг 3.8. Полиморфизм, реализованный с помощью интерфейсов Public Interface IAmusementParkRide Sub Ride() End Interface Public Class RollerCoaster Implements IAmusementParkRide Public Sub IAmusementParkRide_Ride() Console.WriteLine("Here we go") Console.WriteLine("Click, Click .Click") Console.WriteLine("Oh, *&@%") Console.WriteLine("That was great") End Sub End Class Public Class MerryGoRound Implements IAmusementParkRide Public Sub IAmusementParkRide_Ride() Console.WriteLine("OK will go on it") Console.Writeline("Nap Time") Console.WriteLine("Yea its over") End Sub End Class Следующий код находится где-то в программе: Private Sub DayAtTheAmusementPark() Dim oRollerCoaster as New RollerCoaster Dim oMerryGoRound as New MerryGoRound Call GoOnRide(oRollerCoaster) Call GoOnRide(OMerryGoRound) End Sub Private Sub GoOnRide(oRide as IAmusementParkRide) oRide.Ride() End Sub
Наследование в VB.NET Сущность наследования выражается в том, что один класс, называемый подклассом (или дочерним классом), может быть создан на основе другого класса, который, в свою очередь, называется базовым (или родительским) классом. Наследование обеспечивает механизм для создания иерархий объектов. Например, собака (dog) принадлежит классу млекопитающих (mammal), а колли ( c o l l i e ) является представителем класса собак. Таким образом, класс dog наследует свойства и методы класса mammal, а класс c o l l i e , соответственно, наследует свойства и методы классов dog и mammal. В объектно-ориентированном языке существует два типа связей между объектами иерархии — HasA (имеет) и IsA (является). Например, колли IsA собакой и HasA хвост. Реализация наследования является объектно-ориентированным свойством, поддерживающим связи типа IsA, и представляет собой еще один способ, используемый в VB.NET для 48
Глава 3. Концепции объектно-ориентированного программирования
поддержки полиморфизма. Функция может принимать параметр mammal, после чего объект, порожденный из класса mammal, так же как и параметр, может быть передан данной функции.
Реализация наследования Идея об использовании существующего класса в качестве отправной точки при формировании нового класса не могла быть реализована в ранних версиях Visual Basic. И только начиная с пятой версии Visual Basic поддерживает наследование интерфейса посредством ключевого слова implements. Подобная возможность в языке программирования называется реализацией наследования (implementation inheritance). В настоящее время это одна из дополнительных возможностей VB.NET. Предыдущие версии Visual Basic были предназначены для разработки СОМприложений, что являлось препятствием для использования реализации наследования. Visual Basic.NET, в свою очередь, предназначен непосредственно для среды .NET Framework, в основе которой лежит эта возможность. Поддержка реализации наследования является, по всей вероятности, наиболее существенным изменением, внесенным в Visual Basic.NET. В табл. 3.1 приведены новые ключевые слова, введенные в язык вместе с новыми операторами и методами.
Таблица 3.1. Новые элементы языка, относящиеся к реализации наследования Элемент
Контекст
Описание
Inherits
Оператор класса
Указывает класс, из которого наследуется новый класс
Notlnheritabie
Оператор класса
Указывает, что данный класс не может быть унаследован из другого класса
Mustlnherit
Оператор класса
Указывает класс, который должен быть унаследован другим классом
Overridable
Процедура
Указывает процедуру, которая может быть отменена подклассом
NotOverridable
Процедура
Указывает процедуру, которая не может быть отменена в подклассе
MustOverride
Процедура
Указывает процедуру, которая должна быть отменена в подклассе
Overrides
Процедура
Указывает, что данная процедура отменяет процедуру в базовом классе
MyBase
Код
Позволяет коду в классе вызывать код в базовом классе
MyClass
Код
Позволяет коду в классе вызывать код непосредственно
Protected
Функция, процедура, поле, свойство
Указывает, что код в дочернем классе может получить доступ к данному объекту
В примере, который приведен в листинге 3.9, используется целый ряд новых ключевых слов. Код описывает класс с четырьмя свойствами и одним методом. Какой-либо класс, который наследуется из данного класса, должен отменить свойство ClassName. Но свойство BaseClassName не может быть отменено ни одним из дочерних классов. Все остальные свойства и методы могут произвольно отменяться классами, которые наследуются из родительского.
Наследование в VB.NET
49
Листинг 3.9. Класс Person Public Class Person Protected c_sFirstName as String Protected c_sLastName as String MustOverride Readonly Property ClassNameO as String Get ClassName = "Person" End Get End Property NotOverridable Readonly Property BaseClassName() as String Get BaseClassName = "Person" End Get . End Property Overidable Public Property FirstNameO as String Get FirstName = c_sFirstName End Get Set(ByVal Value as string) c_sFirstName = Value End Set End Property Overidable Public Property LastNameO as String Get LastName = c_sLastName End Get Set(ByVal Value as string) c_sLastName = Value End Set End Property Overridable Sub Speak() Console.WriteLine("I am " & c_sFirstName & " " S c_sLastName) Console.WriteLine(" and I am a Person.") End Sub End Class
Этот пример иллюстрирует реализацию наследования в языке VB.NET. Языковые конструкции, согласно основным требованиям Visual Basic, должны быть просты и понятны. В табл. 3.2 сравниваются некоторые ключевые слова, используемые в VB.NET для управления доступностью классов и членов класса, с их эквивалентами в языке С#. Не правда ли, ключевые слова VB.NET более понятны, чем аналогичные ключевые слова языка С#? Таблица 3.2. Ключевые слова языков Visual Basic и С# VB.NET Notlnheritabie
С# Sealed
Mustlnherit
Abstract
MustOverride
Virtual
Inherits
:
Код, приведенный в листинге 3.10, описывает класс, который наследуется из класса Person.
50
Глава 3. Концепции объектно-ориентированного программирования
Листинг 3.10. Класс NewPerson Public Class NewPerson Inherits Person MustOverride Overrides Public Readonly Property ClassNameO as String Get ClassName = "NewPerson" End Get End Property Overrides Sub Speak() Console.WriteLine("My name is " S c_sFirstName S " " & c_sLastName) Console.WriteLine(" and I am a new person.") End Sub End Public При описании этого класса используется целый ряд новых ключевых слов. Например, слово I n h e r i t s указывает на то, что данный класс наследуется. Свойству доступности ClassName присвоены значения M u s t O v e r r i d e и P u b l i c , указывающие на то, что любой дочерний класс, наследуемый из этого класса, должен отменить данное свойство. Ключевое слово O v e r r i d e s указывает, что свойство ClassName и метод Speak родительского класса отменяются новым классом. Свойства c_sFirstName и c_sLastName в новом классе не определены. Эти свойства были определены в родительском классе, а доступности свойств было присвоено значение p r o t e c t e d . Более подробно модификаторы доступности описываются в главе 4, "Методы, свойства, события". I
Эффективная реализация наследования Анализ и проектирование имеют первостепенное значение для эффективного решения с использованием реализации наследования. Одно из главных требований— ясность и простота реализации основных концепций разработки, поэтому в VB.NET поддерживается стремление разработчиков уделить проектированию больше времени. Для того чтобы разрешить наследование каких-либо методов и свойств, пометьте их в родительском классе как O v e r r i d a b l e . Те методы, которые будут отменены при наследовании из основного класса, должны быть отмечены ключевым словом O v e r r i d e s . И наконец, если из данного класса не может быть унаследован какой-либо другой класс, он должен быть отмечен как N o t l n h e r i t a b l e . Требование четкой реализации замысла проекта, предъявляемое к разработчику, позволяет решить проблему "недостаточности базового класса". Рассмотрим пример: в базовый класс вводится новый метод, имеющий то же имя, что и метод производного класса. Метод дочернего класса не был предназначен для отмены метода родительского класса, но в данном случае произошло именно это. Такая ситуация может привести к проблеме, связанной с использованием класса на уровне клиента. Требования декларативного синтаксиса предупреждают появление подобной проблемы BVB.NET.
Включение Как уже указывалось, включение является механизмом осуществления связей HasA (имеет). Этот механизм достаточно прост и не требует поддержки каких-либо элементов языка. В языке Visual Basic для создания связи HasA достаточно одному из Наследование в VB.NET
51
объектов содержать в себе экземпляр другого объекта. Например, для того чтобы в классе P e r s o n определить связь типа HasA с собакой, следует всего лишь ввести код из листинга 3.11. • .
.
Листинг 3.11. Включение, иллюстрирующее связи HasA Private c_oDog as Dog Public Property MyDog() as Dog Get MyDog = c_oDog End Get End Property Public Sub GetADog(ByVal Breed as String, ByVal Name as String) c_oDog = New Dog(Breed,Name) End Sub
Программирование интерфейсов Решения на основе компонентов имеют как положительные, так и отрицательные стороны. Одним из основных преимуществ является возможность создания приложений "по частям". Идея такова: разработка программного обеспечения может выполняться по тем же принципам, что и изготовление каких-либо промышленных образцов, т.е. система создается в виде нескольких отдельных компонентов вместо единой монолитной конструкции. Звучит заманчиво, но, подобно большинству грандиозных проектов, об этом легче сказать, чем сделать. В частности, это относится к более ранним версиям Visual Basic. Теоретически можно взять компонент, который выполняет те или иные действия, и заменить его другим, выполняющим те же действия. К сожалению, чаще всего этого не происходит. В чем же причина? Чтобы улучшить качество функционирования, разработчики предпочитают использовать ранее связывание, что позволяет им связывать компоненты во время компиляции. В свою очередь, для того чтобы воспользоваться ранним связыванием, следует явно определить указанные компоненты, что приводит к созданию конструкции с высокой степенью интеграции компонентов. В конечном итоге это приводит к появлению длинной цепи повторных компиляций. Незначительное изменение одного компонента требует повторной компиляции всех зависящих от него компонентов, а также компонентов, зависящих от этих компонентов, и т.д. В Visual Basic 5.0 появилась возможность хранить определение интерфейса отдельно от компонента, реализующего данный интерфейс. Поэтому необходимость создания зависимых компонентов исчезает. В этом случае для создания экземпляра какого-либо класса достаточно сослаться не на указанный класс, а на интерфейс, реализованный данным классом. Подобная технология позволяет разработчику постоянно изменять фактически используемый компонент. Это особенно важно в том случае, когда компонент и код, его использующий, разрабатываются одновременно. Например, на ранних стадиях разработки может использоваться достаточно простая реализация компонента. Несколько позже можно подключать его более сложную реализацию. А после завершения разработки первоначальная реализация компонента может быть с успехом заменена совершенно другой. Интерфейсы облегчают весь процесс разработки программного обеспечения. С их помощью можно проанализировать элементы созданного проекта, а также значительно упростить сопровождение и выполнение приложений. Интерфейсы чем-то похожи на автомобильные шины. Скажите, трудно ли вам использовать для автомобиля шины только одной марки, типа и стоимости? 52
Глава 3, Концепции объектно-ориентированного программирования
Изменения интерфейсов BVB.NET Расширение возможностей языка VB.NET коснулось и интерфейсов. В настоящее время, например, событие может быть частью интерфейса, что является одним из наиболее существенных дополнений. (В предыдущих версиях Visual Basic существовало только позднее связывание событий.) Механизм определения интерфейса также был изменен. В предыдущих версиях Visual Basic интерфейсы могли быть созданы с помощью класса или же с помощью средств языка описания интерфейсов (IDL). В листинге 3.12 приведен пример нового синтаксиса интерфейса, содержащего событие. Это достаточно простой пример. Но несмотря на это, понятно, что определение интерфейса в языке VB.NET выполняется по тем же законам, что и в языке Visual Basic. Листинг 3.12. Определение интерфейса в VB.NET Public Interface IEmployee Property FirstNamet) As String Property LastNameO As String Function ChangeSalary(ByVal Percentagelncrease as Decimal) mal Event Fired(ByVal ReasonCode as Integer) End Interface
as Deci-
Интерфейсы в VB.NET имеют ряд других улучшений, к которым относится и наследование. Как только интерфейс создается, он может быть реализован в любом из языков платформы .NET Framework. Для реализация интерфейса в среде VB.NET можно воспользоваться методом Visual Basic 5.0 или же новым методом из VB.NET. В листинге 3.13 приведен пример реализации интерфейса в Visual Basic версий 5.0 или 6.0, а в листинге 3.14 — пример создания интерфейса в VB.NET. Листинг3.13. Реализация интерфейса в Visual Basic 6.0 Public Class Employee Implements IEmployee Private c_sFirstName as String Private c_sLastName as String Private c_dSalary as Decimal Private Property IEmployee_FirstName() as String Get IEmployee_FirstName = c_sFirstName End Get Set(ByVal Value as String) c_sFirstName = value End~Set End Property Private Property IEmployee_LastName() as String Get IEmployee_LastName = c_sLastName End Get Set(ByVal Value as String) c_sLastName — value End~Set End Property Private Function IEmployee_ChangeSalary_ (ByVal Percentagelncrease as Decimal) as Decimal Return c_dSalary * (Percentagelncrease / 100) End Function
Программирование интерфейсов
53
'В этом фрагменте не реализовано событие 'Это можно сделать, но код будет достаточно сложным End Class
Синтаксис VB.NET, используемый для реализации интерфейсов, более гибок, прост и понятен (см. листинг 3.14). Листинг 3.14. Реализация интерфейса в стиле VB.NET Public Class Employee Implements IEmployee Private c_sFirstName as String Private c_sLastName as String Private c_dSalary as Decimal Public Property FirstNameofEmployee() as String Implements IEmployee.FirstName Get IEmployee_FirstName = c_sFirstName End Get Set(ByVal Value as String) c_sFirstName = value End~Set End Property Public Property LastNameOfEmployee() as String Implements IEmployee.LastName Get IEmployee_LastName = c_sLastName End Get Set(ByVal Value as String) c_sLastName = value End Set End Property Private Function UpdateSalary(ByVal Percentagelncrease as as Decimal Implements IEmployee.ChangeSalary Return c_dSalary * (Percentagelncrease / 100) End Function "В этом фрагменте не реализовано событие 'Это можно сделать, но код будет достаточно сложным End Class
Decimal)
Новый стиль гораздо более гибок. Например, один класс может реализовать несколько интерфейсов, после чего можно использовать только один метод для его реализации во всех интерфейсах сразу. Реализация методов в языках Visual Basic 5.0 и 6.0 приведена в листингах 3.15 и 3.16. В листингах 3.17 и 3.18 приведен код подобных операций в VB.NET. Листинг 3.15. Реализация метода iEmployee в Visual Basic 5.0 или 6.0 Private Function IEmployee_ChangeSalary() As Decimal Return c_dSalary * (Percentagelncrease / 100) End Function
В листинге 3.16 реализуется дополнительный интерфейс в том же классе и делегируются функциональные возможности предыдущего интерфейса. Листинг 3.16. Реализация методов IEmployee и 1Етр1оуее2 в Visual Basic 5.0 или 6.0 Private Function IEmployee ChangeSalary_ (ByVal Percentagelncrease as Decimal) As Decimal Return c_dSalary * (Percentagelncrease / 100) End Function 54
Глава З. Концепции объектно-ориентированного программирования
Private Function IEmployee2_ChangeSalary_ (ByVal Percentagelncrease as Decimal) As Decimal Return IEmployee_ChangeSalary(Percentagelncrease) End Function В языке VB.NET подобная операция выполняется гораздо проще: следует всего лишь изменить существующие методы реализации предложения (см. листинг 3.17). Листинг 3.17. Реализация метода lEmployee в VB.NET Private Function UpdateSalary(ByVal PercentageToChange as Decimal) as Decimal Implements lEmployee.ChangeSalary Return c_dSalary * (PercentageToChange / 100) End Function VB.NET позволяет добавить к объявлению функции небольшой фрагмент дополнительного кода, указывающего, что данная функция также является реализацией метода IEmployee2 .ChangeSalary (см. листинг 3.18). Листинг 3.18. Реализация методов lEmployee и IEmployee2 в VB.NET Private Function UpdateSalary((ByVal PercentageToChange as Decimal) as Decimal Implements lEmployee.ChangeSalary, IEmployee2.ChangeSalary Return c_dSalary * (PercentageToChange / 100) End Function
Резюме В VB.NET существенно обновлены объектно-ориентированные возможности. Знакомство с VB.NET и со средой .NET Framework связано в основном с изучением новых объектно-ориентированных особенностей языка. Разработчику придется в обязательном порядке потратить некоторое время на освоение многочисленных способов корректного использования описанных средств. С ростом возможностей появляется чувство ответственности, поэтому старайтесь использовать новые возможности разумно. Будьте готовы к исправлению ошибок, которые будут сопровождать первые попытки. В этой главе рассмотрена лишь верхушка "объектно-ориентированного айсберга". Как показывает практика, 80% времени, приходящегося на изучение среды .NET Framework, уходит на освоение ее составных частей. Кроме этого, первостепенную роль играет изучение способов архитектурной реализации.
Резюме
55
ГЛАВА / Методы, свойства, события Классы состоят из методов, свойств и событий. Методы (methods) используются для выполнения действий над объектом; свойства (properties) обеспечивают доступ к данным объекта; события (events) представляют собой реакцию объекта на действия системы, пользователя или других приложений. Методы, свойства и события использовались, конечно, и в предыдущих версиях Visual Basic, но в VB.NET они позволяют обеспечить более широкие функциональные возможности.
Методы Методы представляют собой действия, выполняемые объектом. В Visual Basic существует два типа методов: процедуры и функции. Процедуры и функции классов VB.NET практически ничем не отличаются от подобных процедур и функций Visual Basic. Но следует подчеркнуть, что VB.NET внес несколько неуловимых на первый взгляд изменений.
Изменения параметров Как вы знаете, ключевые слова ByRef и ByVal определяют способ передачи параметров. Теперь вместо ключевого слова ByRef, задаваемого при объявлении аргументов, по умолчанию используется ByVal. При преобразовании приложений, созданных в предыдущих версиях Visual Basic, в том случае, когда это необходимо, следует явно указывать ByRef. VB.NET все еще поддерживает необязательные параметры. Несмотря на это, при объявлении таких параметров им следует задать значения по умолчанию. Кроме этого, в VB.NET не поддерживается функция I sMi s s ing. В языке VB.NET свойства могут быть переданы как в процедуру, так и из нее. Пример описанных изменений приведен в листинге 4.1. В этом примере показано, как изменяется свойство объекта FirstName. Подобная операция не могла быть выполнена в Visual Basic 6.0.
Листинг 4.1. Параметр свойства ByRef Public Sub.ChangeName(ByRef Name as String) Name = "Mr. " & Name End Sub 'Код, использующий эту функцию Call ChangeName(oEmployee.FirstName)
Вызов процедуры Теперь для вызова процедуры или функции в VB.NET следует заключить объявляемый аргумент данной процедуры (или функции) в круглые скобки. Ниже приведены два способа вызова процедуры: первый вызов разрешен в Visual Basic 6.0, но не допустим более в VB.NET; второй содержит синтаксис процедуры, допустимый в VB.NET. ChangeName sFirstName ChangeName (sFirstName)
Возврат значений В предыдущих версиях Visual Basic возвращаемое значение, как показано в листинге 4.2, присваивалось имени функции. Подобный способ допустим также и в VB.NET, но лучше применять синтаксис функции, в котором используется новый возвращающий значение оператор Return. Синтаксис оператора Return приведен в листинге 4.3. ЛИСТИНГ 4.2. Возврат значения в Visual Basic 6.0
Public Function MyFunction() as String MyFunction = "Hello World" End Function Оператор R e t u r n возвращает значение, определяемое именованной переменной, константой или функцией, которая является параметром (как показано в листинге 4.3). Обратите внимание, что какой-либо код, следующий после оператора возврата, не выполняется. Это одно из отличий от Visual Basic 6.0, в котором происходит дальнейшее выполнение кода. Листинг 4.3. Возврат значения в VB.NET Public Function MyFunction() as String Return "ReturnValue" End Function В листинге 4.4 приведена методика, обычно применяемая в Visual Basic 6.0, которая не будет работать при использовании оператора Return. Листинг 4.4. Инициализация возвращаемого функцией значения Public Function MyFunction(ByVal SomeFlag as Boolean) as String MyFunction = "One Value" 'Установка возвращаемого значения по умолчанию If SomeFlag then MyFunction = "Another Value" 'Установка нового значения End If End Function Если вы попытаетесь выполнить эту операцию в VB.NET, используя оператор Return, результат будет совершенно другим (листинг 4.5). 58
Глава 4. Методы, свойства, события
Листинг 4.5. Оператор Return прекращает выполнение функции Public Function MyFunction(ByVal SomeFlag as Boolean) as String Return "One Value" 'Только этот код работает If SomeFlag then MyFunction = "Another Value" 'Установка нового значения End If End Function
Статические процедуры Переменные S t a t i c используются для хранения значений между вызовами. Процедура, объявленная в предыдущих версиях Visual Basic как S t a t i c , означает, что все ее переменные также объявлены как S t a t i c . Этот метод в VB.NET больше не используется.
Общедоступные методы Сейчас стало возможным объявить процедуру, которая может использоваться как с экземпляром создаваемого класса, так и без него. Для этого следует объявить данную процедуру как Shared. Пример объявления общедоступного метода приведен в листинге 4.6. Листинг 4.6. Общедоступный метод в VB.NET Public Class Employee Public Shared Sub AddEmployee(ByVal FirstName as String, ByVal LastName as String, ByVal Department as String, ByVal SSN as String) 'Код, сохраняющий новую учетную запись пользователя в базе данных End Sub End Class Общедоступные методы могут быть вызваны из экземпляра класса или непосредственно из класса. Приведем пример вызова с помощью экземпляра класса: Dim oEmployee as New Employee)) oEmployee.AddEmployee("Fred","Flinstone",,"Rock Breaking","111111111") И непосредственно через класс: Employee.AddEmployee("Fred","Flinstone","Rock Breaking","111111111")
Перегрузка функции Перегрузка позволяет разработчику определить несколько функций с одинаковым именем, но с разными параметрами. Списки параметров могут содержать одинаковое или разное число параметров, которые, в свою очередь, могут быть как одного, так и разных типов. На основании списка параметров компилятор определяет во время компиляции, какая из версий данной функции должна быть вызвана. В том случае, если функция возвращает какое-либо значение, типы данных списка параметров и возвращаемый тип образуют сигнатуру (signature). В листинге 4.7 приведен пример двух функций, выполняющих совершенно разные действия, но имеющих одну и ту же сигнатуру. ЛИСТИНГ 4.7. Сигнатуры функций
Public Function FunctionOne(ByVal companyName as String, ByVal companylD as Integer) as String End Function Public Function FunctionTwo.(ByVal firstName as String,
Перегрузка функции
59
ByVal employeeID as Integer) End Function
as String
Перегрузка функций является мощным средством, позволяющим создавать во время проектирования достаточно гибкие конструкции. Пример перегрузки функций приведен в листинге 4.8 (обратите внимание, что функции имеют одинаковое имя, но разные сигнатуры). В языке VB.NET необходимо явно объявить перегрузку функций, используя ключевое слово O v e r l o a d s . Листинг 4.8. Перегрузка функции Public Overloads Function AddValues(ByVal Valuel as Integer, ByVal Value2 as Integer) As Integer Return Valuel + Value2 End Function Public Overloads Function AddValues(ByVal Valuel as Integer, ByVal Value2 as Integer, ByVal Value3 as Integer) as Integer Return Valuel + Value2 + Value3 End Function
Свойства В VB.NET существуют различные методы объявления данных классов для внешнего использования. Наиболее простой — создание полей P u b l i c : P u b l i c FirstName as S t r i n g Лучше не использовать открытые поля по многим причинам. Прежде всего это препятствует управлению доступа к данным, а также проверке правильности данных с помощью кода. Рассмотрим следующую ситуацию: вместо FirstName есть поле, которое содержит элемент ItemCount из базы данных. Для того чтобы воспользоваться данными поля ItemCount, следует в первую очередь выполнить поиск в базе данных, что влечет за собой написание дополнительного кода. В результате приходится выполнять больший объем работы, а также создавать доступ к базе данных, который, возможно, никогда не будет использован. Значение ItemCount может быть реализовано как свойство, что позволяет извлекать информацию из базы данных только по мере необходимости. Кроме того, значения, объявленные как свойства, позволяют ограничивать число пользователей, имеющих к ним доступ. Свойства в VB.NET остались неизменными, но синтаксис свойств изменился, став проще и понятнее. В листинге 4.9 приведен пример определения свойств в предыдущих версиях Visual Basic. Листинг 4.9. Процедуры-свойства в Visual Basic 4.0-6.0 Public Property Let FirstName(ByVal Value as String) c_sFirstName — Value End Property
Public Property Get FirstName() FirstName = c_sFirstName End Property
as String
Если свойство является объектом, используется процедура P r o p e r t y Set вместо P r o p e r t y Let. Обратите внимание, что процедуры P r o p e r t y Get и P r o p e r t y Let (или Set) обрабатываются, как два независимых блока. При отсутствии оператора P r o p e r t y 60
Глава 4. Методы, свойства, события
Let свойство будет применимо только для чтения, а при отсутствии оператора P r o p e r t y Get — только для записи. Синтаксис описанных процедур в VB.NET существенно изменился. В листинге 4.10 приведен пример определения свойств в языке VB.NET. Листинг4.10. Определение свойств в VB.NET Private c_sFirstName as string Public Property FirstNameO as String Get Return c_sFirstName End Get Set(ByVal Value as string) c_sFirstName = Value End Set End Property Обратите внимание, что весь код представляет собой монолитный блок, который не разбивается на отдельные независимые фрагменты. Для создания свойств только для чтения или только для записи необходимо явно отметить указанные свойства как Read-Only или Write-Only. (Процедуры P r o p e r t y Get и P r o p e r t y Let, позволяющие создавать различные уровни доступа, в языке VB.NET больше не используются.) В листинге 4.11 приведен пример определения свойства Read-Only, а в листинге 4.12 — Write-Only. Листинг 4.11. Свойство Read-Only Private c_sFirstName as string Public Readonly Property FirstNameO as String Get Return c_sFirstName End Get End Property
Листинг 4.12. Свойство Write-Only Private c_sFirstName as string Public WriteOnly Property FirstNameO as String Set(ByVal Value as String) с sFirstName = Value End Set End Property
Было внесено еще одно небольшое изменение, относящееся к свойствам VB.NET. В предыдущих версиях, например, для создания заданных по умолчанию свойств использовалось довольно "странное" диалоговое окно. Теперь появился модификатор D e f a u l t , позволяющий создавать свойства по умолчанию (листинг 4.13). Существует одно важное отличие: заданное по умолчанию свойство должно содержать индекс, поэтому значения по умолчанию могут быть присвоены только некоторым типам массивов или коллекций. Листинг4.13. Свойство Default в VB.NET Public Default Property ChildrenNames(ByVal Index as Integer) as String Get Return c_sChildren(Index) End Get Set(ByVal Value as String) c_sChildren(Index) = Value End Set End Property
Свойства
61
Общедоступные свойства Разработчикам иногда приходится создавать поля и свойства, имеющие одинаковое значение для всех экземпляров класса. В предыдущих версиях Visual Basic для выполнения этой задачи существовал только один способ, состоящий в использовании модулей. Эта технология достаточно часто приводила к побочным эффектам. Подобные функциональные возможности в VB.NET обеспечиваются непосредственно в классах, для чего поле или свойство класса объявляется как общедоступное — Shared. В листинге 4.14 приведен пример класса, имеющего общее свойство. Листинг 4.14. Пример свойства Shared Public Class Employee Public Shared EmployeeCount as I n t e g e r Private m_sFirstName as String P r i v a t e m_iEmployeeID as Integer P r i v a t e Sub New(ByVal EmployeelD as Integer) 'Получение информации из базы данных и сохранение ее в переменной m_iEmployeeID = EmployeelD EmployeeCount = EmployeeCount + 1 End Sub Public Property FirstNameO as S t r i n g Get FirstName = m_sFirstName End Get Set(ByVal Value as String) m sFirstName = Value End~Set End Property Public Readonly Property EmployeelD() as Integer Get EmployeelD = m_iEmployeeID End Get End Property 'Следующая процедура взята из предыдущего примера Public Shared Sub AddEmployee(ByVal FirstName as S t r i n g , _ ByVal LastName as S t r i n g , ByVal Department as S t r i n g , _ ByVal SSN as String) 'Код, сохраняющий новую учетную запись пользователя в базе данных End Sub End Class
Общедоступные свойства, как и общедоступные методы, могут быть вызваны без создания экземпляра класса, как показано в листинге 4.15. Листинг 4.15. Использование общедоступного свойства без создания экземпляра класса Dim iEmployeeCount as Integer iEmployeeCount = Employee.EmployeeCount
Пример общедоступного свойства, вызываемого с помощью созданного экземпляра класса, приведен в листинге 4.16.
Листинг 4.16. Использование общедоступного свойства посредством экземпляра класса Dim oEmployee as New Employee(123) Dim iEmployeeCount as I n t e g e r iEmployeeCount = oEmployee.EmployeeCount
Общедоступные свойства представляют собой достаточно мощный механизм. Например, можно изменить код листинга 4.16 таким образом, чтобы использовать при первой не62
Глава 4. Методы, свойства, события
обходимости для загрузки поля EmployeeCount не общедоступное поле, а общедоступное свойство. Пример такого общедоступного свойства приведен в листинге 4.17. Одно и то же закрытое поле совместно используется всеми экземплярами класса для хранения значения EmployeeCount. Другими словами, при обращении к свойству EmployeeCount из любого экземпляра класса Employee будет возвращено одно и то же значение. Более того, можно извлечь значение только с помощью класса, т.е. без создания экземпляров данного класса. Листинг 4.17. Поиск в базе данных Public Class Employee Private Shared c_iEmployeeCount As Integer Private c_sFirstName As String Private с iEmployeelD As Integer Private Sub New(ByVal EmployeelD As Integer) 'Получение информации из базы данных и сохранение ее в переменной c_iEmployeeID = EraployeelD End Sub Public Property FirstNameO As String Get FirstName = с sFirstName End Get Set(ByVal Value As String) c_sFirstName = Value End Set End Property Public Readonly Property EmployeelD() As Integer Get EmployeelD = c_iEmployeeID End Get End Property 'Получение числа сотрудников тогда, когда это необходимо Public Shared Readonly Property EmployeeCount() As Integer Get If c_iEmployeeCount = -1 Then 'Извлечение из базы данных числа сотрудников 'и сохранение в общедоступном поле c_iEmployeeCount = CountRetreivedFromDatabase End If Return c_iEmployeeCount End Get End Property 1 Следующая процедура взята из предыдущего примера Public Shared Sub AddEmployee(ByVal FirstName As String,_ ByVal LastName As String, ByVal Department As String,_ ByVal SSN As String) 'Код, сохраняющий новую учетную запись пользователя в базе данных c_iEmployeeCount = c_iEmployeeCount + 1 End Sub End Class
События События играют центральную роль при разработке приложений. События происходят, например, при воздействии на элементы управления формы (скажем, при щелчке на кнопке) и являются в данном случае реакцией на внешнее воздействие со стороны польСобытия
63
зователя. Кроме этого, события могут использоваться для обращения к какой-либо программе с уведомлением об изменении состояния объекта. В многопоточной среде, например .NET Framework, событием является передача сообщения о завершении задачи одного из потоков. Visual Basic ввел мир Windows в программирование на основе событий; это именно то, от чего следовало бы избавиться в первую очередь. Кроме этого, в ранних версиях существовали определенные проблемы реализации событий. Возможности событий в .NET Framework были расширены, что позволило решить некоторые проблемы, а также значительно улучшить управление событиями. Определяющим в этих улучшениях является концепция делегатов.
Делегаты Теперь модель события в Visual Basic.NET выполнена на основе концепции делегатов. Делегат (delegate) — это объект, который может вызывать объектные методы. Делегат может быть представлен в виде указателей функции, обеспечивающих типовую безопасность. Процесс создания делегатов вручную в VB.NET достаточно прост (листинг 4.18). ЛИСТИНГ 4.18. Пример делегата Delegate Function MyCompareDelegate(ByVal x As I n t e g e r , ByVal у As I n t e g e r ) As Boolean Sub MySub(ByVal MyDelegate as MyCompareDelegate) MyDelegate.Invoke(5,3) End Sub Function CompareLow(ByVal X as I n t e g e r , ByVal Y as I n t e g e r ) as Boolean If X > Y then Return True Else Return False End If End Function Function CompareHigh(ByVal X as I n t e g e r , ByVal Y as I n t e g e r ) as Boolean > If X < Y then Return True Else Return F a l s e End I f End Function Sub Main() Call MySub(AddressOf Me.CompareLow) Call MySub(AddressOf Me.CompareHigh) End Sub
В большинстве случаев вручную создавать делегаты не нужно — все сделает VB.NET. Класс делегата, называемый <EventName>EventHandler, позволяет неявно определить оператор Event. Класс делегата является вложенным классом по отношению к тому классу, в котором содержится оператор Event. Сигнатура класса практически ничем не отличается от сигнатуры события.
Обработчики событий В предыдущих версиях Visual Basic существовал только один способ создания обработчика событий — разработка процедуры, синтаксис которой приведен в листинге 4.19. 64
Глава 4. Методы, свойства, события
Листинг 4.19. Синтаксис обработчика события в предыдущих версиях Visual Basic ObjectName_EventName(Event Parameters) Например, событие, происходящее при щелчке мышью на кнопке, которой присваивалось имя B u t t o n l , определялось как событие B u t t o n l _ C l i c k . Синтаксис событий в среде .NET Framework и определяется так: SuB EventHandlerNaine(ByVal sender As Object, ByVal e As System.EventArgs) Handles Object.Event В предыдущих версиях Visual Basic параметры событий передавались явно. В .NET Framework параметры включены во второй параметр, который фактически представляет собой коллекцию. В листинге 4.20 приведен пример обработчика события Form MouseDown приложения Windows Form. Класс System. EventArgs является подклассом, который вводит значения координат X и Y, а также свойства кнопки, позволяющие обеспечить функциональные возможности мыши. Листинг 4.20. Обработчик событий Form MouseDovm P u b l i c Sub Forml_MouseDown(ByVal sender As Object, ByVal e As System.Windows Forms.MouseEventArgs) Dim Button As system.Windows Forms.MouseButtons Dim X As I n t e g e r Dim Y As Integer Button = e.Button X = e.X Y = e.Y End Sub В VB.NET существует несколько методов, используемых для назначения обработчиков событий. Например, добавлено ключевое слово Handles, позволяющее назначать обработчики событий во время разработки. Как показано в листинге 4.21, Handles позволяет обрабатывать несколько различных событий с помощью одного обработчика. Обратите внимание, что для выполнения этой задачи все обработчики событий должны совместно использовать одну и ту же сигнатуру. Листинг 4.21. Общий обработчик событий Protected Sub CommonEventHandler(ByVal sender As Object, ByVal e As System.EventArgs) Handles Buttonl.Click, Button2.Click, Forml.Click If sender Is forml Then msgbox("Form Clicked") Else msgbox(CType(sender, Button).text) End If End Sub Ключевое слово Handles позволяет создавать обработчики событий во время разработки. Но иногда приходится это делать и во время выполнения. Для этого в VB.NET добавлены новые операторы AddHandler и RemoveHandler. Как следует из названия, оператор AddHandler используется для назначения обработчика событий тому или иному событию, а оператор RemoveHandler — для удаления созданного назначения. Ниже приведен синтаксис и примеры использования операторов AddHandler и RemoveHandler. Синтаксис операторов AddHandler и RemoveHandler: AddHandler O b j e c t . E v e n t , Delegate RemoveHandler O b j e c t . E v e n t , Delegate
События
65
Примеры использования операторов AddHandler и RemoveHandler: AddHandler B u t t o n l . C l i c k , AddressOf me.EventHandler RemoveHandler B u t t o n l . C l i c k , AddressOf me.EventHandler В листинге4.20 ключевые слова AddressOf и me.EventHandler используются для создания делегата. Впервые слово AddressOf было введено в Visual Basic 5.0 для обработки вызовов API, использующих необходимые обратные вызовы. В VB.NET ключевое слово AddressOf можно применять для создания делегата любой функции, процедуры или метода.
Создание событий Возможность создания событий существовала в Visual Basic начиная с версии 5.0. Процесс создания событий всегда был достаточно прост, что сохранилось и в VB.NET. Синтаксис этой операции практически не изменился. Для того чтобы объявить событие в классе, достаточно воспользоваться ключевым словом Event для описания имени события и параметров, которые передаются событием обработчику событий: P u b l i c Event EventName(event parameters) Единственное, на что следует обратить внимание: параметры события в .NET Framework могут быть определены точно так же, как и само событие. Памятуя об этом, можно определить событие следующим образом: P u b l i c Event EventName(ByVal sender as Object, ByVal e as System.EventArgs) Определение параметров событий происходит примерно по тем же правилам, что и определение параметров процедур или функций. События могут быть объявлены как ByVal или ByRe f, но не могут содержать какие-либо именованные или необязательные параметры. Кроме того, события не могут иметь возвращаемых значений.
Генерация событий Генерация событий происходит настолько же просто (или даже еще проще), как и создание событий. В VB.NET используется тот же синтаксис, что и в Visual Basic 5.0 или 6.0. Для генерации событий внутри класса предназначен оператор R a i s e E v e n t , которому в качестве аргумента передается имя события: RaiseEvent EventName(параметры события)
Использование EventArgs Класс System. EventArgs определяет базовый класс аргументов события (т.е. параметров). Пример использования этого класса приведен в листинге 4.22. Листинг4.22. Параметры обработчика событий (наследование System.EventArgs) Public Class MyMouseEventArgs Inherits System.EventArgs Public Readonly Property XPositionO As Integer Get Return cursor.Position.X End Get End Property Public Readonly Property YPositionO As Integer Get 66
Глава 4. Методы, свойства, события
Return Cursor.Position.Y End Get End Property End Class В листинге 4.23 приведен код события, использующего класс EventArgs.
Листинг 4.23. Использование созданного класса EventArgs Public Event MouseOver(ByVal Sender as Object, ByVal e as System.EventArgs) Public Sub TestRaiseEvent() RaiseEvent Ctype(MouseOver(Me,New MyMouseEventArgs).System.EventArgs) End Sub Private WithEvents MyEventObject as MyEventObjectTester Private Sub MyEventHandler(ByVal Sender as Object, ByVal e as System.EventArgs) Handles MyEventObject.MouseDown, Forml.Click Dim oMyMouseEventArgs as MyMouseEventArgs If Not Sender is Forml Then oMyMouseEventArgs = Ctype(e, MyMouseEventArgs) Console.WriteLine(e.XPosition.ToString() ) Console.WriteLine(e.YPosition.ToString()) Else Console.WriteLine("Form Raised Click Event") End If End Sub
Атрибуты Одним из наиболее мощных нововведений .NET Framework является новая модель программирования на основе атрибутов. Атрибуты {attributes) представляют собой метки, размещенные внутри программного кода, которые могут быть применены к сборкам, классам, полям, методам или свойствам. Атрибуты добавляют декларативные функциональные возможности как в .NET Framework, так и в создаваемый код. Синтаксис, используемый для добавления атрибутов, достаточно прост, но следует заметить, что существует несколько важных правил. Начнем с базового синтаксиса, представленного следующим выражением: В листинге 4.24 приведен пример атрибута WebMethod, объявленного на уровне метода. ЛИСТИНГ 4.24. Атрибут WebMethod
<WebMethod()> Public Function GetEmployees() as DataSet Dim oDataSet as New DataSet 'Код для создания набора данных Return oDataSet End Function / Атрибут WebMe thod не содержит каких-либо обязательных параметров, поэтому используется в таком виде, как показано в листинге 4.24. Для объявления атрибутов на уровне сборки в качестве меток атрибута используется первая строка кода, найденного в исходном файле, причем модификатор должен быть размещен в метке: Атрибуты
67
Для того чтобы объявить атрибуты на уровнях класса, метода, поля или свойства, метки атрибута должны быть вложены соответственно в объявление класса, метода, поля или свойства перед его именем. Пример использования атрибута WebMethod описанных уровней приведен в листинге 4.25. Листинг 4.25. Объявление функции как WebMethod <WebMethod()> Public Function GetClientName(ByVal ClientID as Integer) as String End Function Атрибут WebMethod объявляет метод как службу. В этом случае среда исполнения CLR (Common Language Runtime) изменяет информацию в виде XML. Интеграция с Visual Studio.NET частично выполнена с помощью атрибутов. В листинге 4.26 приведен пример использования атрибутов для определения формата отображения свойств серверного элемента управления ASP.NET на странице свойств в Visual Studio.NET. ЛИСТИНГ 4.26. Свойства в окне страницы свойств Property EndDateO As Date Get Return CType(State("EndDate"), Date) End Get Set c_dteEndDate = Value State("EndDate") = Value If c _ d t e S t a r t D a t e < c_dteEndDate Then CreateTimeTable() End I f End Set End Property
Свойство EndDate (см. листинг 4.26) содержит ряд различных атрибутов. Атрибут B i n d a b l e указывает на то, что свойство может быть связано; C a t e g o r y определяет, какая категория свойств должна быть включена в окно просмотра свойств (в данном случае— " D a t e s " ) ; DefaultValue присваивает свойству значение по умолчанию. И наконец, атрибуты играют очень важную роль в межкомпонентном взаимодействии в .NET Framework. В листинге 4.27 показано использование атрибутов в процессе упаковки запроса (другими словами, маршалинга) с использованием стандартных механизмов СОМ. Листинг 4.27. Использование атрибутов для выполнения стандартного маршалинга Declare Auto Sub CopyFile Lib "Kernel32" (ByVal <MarshalAs(UnmanagedType.LPTStr)> existingfile As String, ByVal <MarshalAs(UnmanagedType.LPTStr)> newfile As String, ByVal failifexists As Boolean)
Резюме Создание среды .NET Framework повлекло за собой появление различных новых возможностей, относящихся к событиям и моделям объектно-ориентированного программирования в Visual Basic. Наиболее существенное нововведение среды .NET Framework — работа с атрибутами свойств, методов и событий.
68
Глава 4. Методы, свойства, события
Создание и удаление объектов В структуру новой версии языка Visual Basic добавлены конструкторы. Конструкторы (constructors) обеспечивают возможность инициализации объекта непосредственно после его создания, а также позволяют передать объекту необходимые параметры во время создания. Язык VB.NET разрешает использование конструкторов как в классах, так и во встроенных типах, например целочисленных и строчных.
Конструкторы Конструкторы встроенных типов называются также инициализаторами (initializers). В листинге 5.1 приведен пример метода, используемого в предыдущих версиях Visual Basic для инициализации целого числа. В этом случае объявление переменной и ее инициализация происходят в два этапа. ЛИСТИНГ 5.1. Инициализация целого числа в преды-
дущих версиях Visual Basic Dim I as integer 1 = 5 В .NET Framework язык Visual Basic был расширен, что позволяет инициализировать переменную при ее объявлении. Пример, приведенный в листинге 5.2, показывает, как происходит описанный процесс в VB.NET. ЛИСТИНГ 5.2. Инициализация целого числа в VB.NET Dim I as integer = 5
Событие C l a s s _ I n i t i a l i z e Visual Basic поддерживает начиная с версии 4.0. Это событие выполняется в том случае, когда во время создания объекта не существует какого-либо способа передачи ему необходимых параметров. Например, если понадобится параметрически управляемая инициализация, придется ввести метод инициализации в класс, как показано в листинге 5.3.
Листинг 5.3. Инициализация объекта в Visual Basic 4.0-6.0 Set oEmployee = New CEmployee oEmployee.Init iEmployeelD 'В проекте есть файл Cemployee.ds со следующим кодом Public Sub Init(ByVal employeelD as I n t e g e r ) Dim oDBConnection as ADODB.Connection Dim oDBCommand as ADODB.Command Dim oDBRecordSet as ADODB.RecordSet 1 Выполните код доступа к базе данных для возврата 'Employee и заполнения свойств End Sub
В языке VB.NET событие C l a s s _ I n i t i a l i z e заменено конструкторами класса. Конструктор определяется с помощью процедуры New. Для того чтобы в одном классе существовало несколько конструкторов, следует воспользоваться перегрузкой функций. Перегрузка — это возможность выбора компилятором различных реализаций одной и той же функции, в зависимости от типов ее параметров при вызове. В листинге 5.4 приведен пример кода класса VB.NET, использующего перегрузку и несколько различных конструкторов. Листинг 5.4. Перегруженные конструкторы VB.NET Public Class Employee Private c_sFirstNarrie as s t r i n g Private c_sLastName as String Public Overloads Sub New() MyBase.NewO 'Вызов конструктора базового класса End Sub Public Overloads Sub New(ByVal FirstName as String, ByVal LastName as String) MyBase.New()' Вызов конструктора базового класса Me.FirstName = FirstName Me.LastName = LastName End Sub Public Property FirstName() as String Get FirstName = c_sFirstName End Get Set(ByVal Value as String) c_sFirstName = value End~Set End Property Public Property LastName() as String Get LastName = c_sLastName End Get Set (ByVal Value as String) c_sLastName = value End Set End Property End Class
Первая строка программного кода в конструкторе класса является обращением к специальной переменной MyBase.New, относящейся к базовому классу, из которого наследуется данный класс. (Не забывайте, по крайней мере, что все классы наследуются из System.Object.) В том случае, если вы не создаете конструктор, он будет автоматически создан компилятором. После этого компилятор вызовет переменную MyBase. New. 70
Глава 5. Создание и удаление объектов
Деструкторы Событие C l a s s _ T e r m i n a t e точно так же, как и событие C l a s s _ I n i t i a l i z e , поддерживается языком Visual Basic начиная уже с версии 4.0. Выполнение события C l a s s _ T e r m i n a t e происходит после удаления последней ссылки на экземпляр какоголибо объекта. Подобные функциональные возможности реализованы на основе СОМмодели управления ресурсами, т.е. на подсчете существующих ссылок. В среде .NET Framework, как отмечается в главе 10, "ADO.NET", подсчет ссылок не используется. Поэтому событие C l a s s T e r m i n a t e для данного случая является не более чем частью языка программирования. При наличии явной очистки ресурсов, которая необходима для завершения класса, следует ввести в программный код метод F i n a l i z e , представленный в листинге 5.5. Листинг 5.5. Метод Finalize Protected Sub Finalize() 'Закрытие соединения с базой данных oDBConnection.Close End Sub Класс, содержащий метод F i n a l i z e , отмечается компилятором, как класс, требующий завершения. Когда процесс очистки памяти от ненужных данных, или "сборщик мусора", встречает класс с методом F i n a l i z e , он перемещает экземпляр класса в очередь объектов, нуждающихся в завершении. После завершения процесса "сборки мусора", т.е. утилизации памяти, освобождаемой в процессе работы программы, происходит вызов метода F i n a l i z e объектов, находящихся в очереди на завершение. Следует подчеркнуть, что обращение к методу F i n a l i z e происходит через некоторое время после удаления последней ссылки, относящейся к данному экземпляру класса. Постарайтесь избежать использования этого метода при последующей разработке программных компонентов. Их использование значительно замедляет процесс "сборки мусора". Созданный объект должен быть сразу же очищен от ненужных данных. Это особенно важно в том случае, когда объект содержит дефицитные ресурсы, к которым относятся, например, подключения к базе данных, дескрипторы файлов и т.п. Для этих целей следует воспользоваться не методом F i n a l i z e , а шаблоном проектирования Dispose.
(ЧтЧто такое шаблон проектирования? Шаблон проектирования представляет собой описание периодически возникающей проблемы, содержащее одну из моделей ее решения. Таким образом, шаблон проектирования описывает не только существующую проблему, но и способ ее решения. Шаблон достаточно прост. Все, что нужно сделать, — реализовать интерфейс System. I D i s p o s a b l e и его метод D i s p o s e . В том случае, если разработчик не сможет обратиться к методу D i s p o s e , требуемая очистка может быть выполнена с помощью метода F i n a l i z e . Существует еще одна потенциальная проблема шаблона проектирования Dispose, возникающая при повторном вызове метода F i n a l i z e из метода Dispose. Для того чтобы выйти из этой ситуации, при условии, что данный класс содержит метод F i n a l i z e , необходимо вызвать метод S u p r e s s F i n a l i z e из метода Dispose. Синтаксис метода Supp r e s s F i n a l i z e приведен в листинге 5.6. Деструкторы
71
Листинг 5.6. Подавление повторного завершения System.GC.SuppressFinalize() Шаблон проектирования Dispose используется непосредственно в среде .NET Framework. Например, при создании формы Windows конструктор формы добавляет обращение к методу Dispose. В листинге 5.7 приведена часть кода, сгенерированного конструктором форм Windows. Листинг 5.7. Метод Dispose в форме Windows Public Overrides Sub Dispose О MyBase.Dispose() If Not (components Is Nothing) Then components.Dispose() End If End Sub
Модификаторы доступности Модификаторы доступности управляют видимостью классов, методов, свойств и событий. В Visual Basic 6.0 доступность определяется свойствами класса, а также модификаторами доступности методов, свойств и событий.
Модификаторы классов Значения свойства I n s t a n c i n g , определяющего способ создания экземпляров класса в Visual Basic 6.0, представлены в табл. 5.1. Таблица 5.1. Значения свойства instancing в Visual Basic 6.0 Значения свойства Instancing Private
Описание Доступ к этому классу разрешен только из проекта, где он создан
PublicNotCreatable
Объекты этого класса могут использоваться другими приложениями только в том случае, если объекты созданы в проекте, где находится данный класс
SingleUse
Объекты этого класса могут быть созданы другими приложениями, но каждый объект этого класса, создаваемый клиентом, запускает новый экземпляр компонента
GlobalSingleUse
Объекты этого класса доступны для других приложений и могут быть созданы вне проекта, в котором находится данный класс. Это значение свойства не поддерживается VB.NET
MultiUse
Объекты этого класса могут быть созданы другими приложениями. Независимо от количества создаваемых объектов, создается только один экземпляр компонента
GlobalMultiUse
Объекты этого класса могут быть созданы другими приложениями. Это значение свойства не поддерживается VB.NET
По сравнению с предыдущей версией уровни доступности классов в VB.NET несколько изменились. В табл. 5.2 приведены уровни доступности классов, существующие в VB.NET.
72
Глава 5. Создание и удаление объектов
Таблица 5.2. Уровни доступности классов в VB.NET Уровни доступности
Описание
Public
Объекты класса доступны без ограничений
Private
Объекты класса доступны только в пределах текущего пространства имен.
Protected
Объекты класса доступны производным типам
Friend
Объекты класса доступны другим типам в пределах одного пространства имен Свойства доступа данного класса представляют собой сочетание свойств Protected и Friend
Это относится также и к объектам вложенных классов
Protected Friend
В табл. 5.3 представлены свойства доступности классов Visual Basic 6.0, а также способы назначения подобных свойств в VB.NET (если это возможно). Таблица 5.3. Отношение свойств классов Visual Basic 6.0 и VB.NEJ Visual Basic 6.0
Visual Basic.NET
Private
Класс отмечается как P r i v a t e
. PublicNotCreatabie
Класс отмечается как P r i v a t e , конструктор — как F r i e n d
SingleUse
He поддерживается
GlobalSingleUse
He поддерживается
MultiUse
Класс отмечается как P u b l i c , конструктор — как P u b l i c
GlobalMultiUse
He поддерживается
Модификаторы методов и свойств Использование модификаторов не ограничивается только классами. В VB.NET существует также набор модификаторов, которые позволяют изменять доступность методов и свойств. В табл. 5.4 представлены модификаторы, существующие в Visual Basic 6.0. Таблица 5.4. Уровни доступности методов и свойств в Visual Basic 6.0 Уровни доступности
Описание
Private
Доступны только для класса, в котором они были созданы
Public
Доступны за пределами класса, в котором они были созданы
Friend
.
Доступны в пределах проекта, в котором они были созданы, но являются закрытыми по отношению к внешнему коду
Уровни доступности методов и свойств VB.NET по сравнению с Visual Basic 6.0 значительно изменились. Модификаторы языка VB.NET представлены в табл. 5.5. Таблица 5.5. Уровни доступности методов и свойств в VB.NET Уровни доступности Public
Описание Доступны без ограничений
Private
Доступны только в том классе, в котором они были созданы
Protected
Доступны только в классе, в котором они были созданы, или в каких-либо других классах, производных от класса, в котором они были созданы
Модификаторы доступности
73
Окончание табл. 5.5 Уровни доступности
Описание
Friend
Доступны в коде в пределах одного и того же пространства имен
Protected Friend
Свойства доступности представляют собой сочетание свойств P r o t e c t e d И Friend
Резюме В настоящее время Visual Basic представляет собой полностью объектно-ориентированный язык программирования. Это объясняется требованиями среды .NET Framework, которая является объектно-ориентированной. Кроме этого, Visual Basic — наиболее самодокументированный язык, доступный в настоящее время для .NET Framework.
74
Глава 5. Создание и удаление объектов
ГЛАВА 6 Создание проектов VB.NET VB.NET поддерживает все типы проектов, доступные в среде .NET Framework, к которым относятся службы Windows (Windows Services) и консольные приложения (console applications). В то же время из VB.NET удалены некоторые типы проектов, доступные в более ранних версиях. В этой главе приведен краткий обзор каждого из типов проекта, доступных в VB.NET. На рис. 6.1 показаны основные компоненты .NET Framework, с которыми вы познакомитесь в этой главе.
Неподдерживаемые типы проектов Следует заметить, что все типы проектов из предыдущих версий Visual Basic в среде .NET Framework не поддерживаются. В Visual Basic 6.0 имеется ряд Webприложений, которые в .NET Framework более недоступны. В их число входят WebClasses, DHTML Applications и ActiveX Documents. Существующие средства миграции позволяют преобразовать проекты WebClasses в Web Forms. Эти средства не поддерживают преобразование проектов DHTML Applications и ActiveX Documents. Кроме того, удалена поддержка проектов Data Report.
Библиотеки классов Visual Basic версий 5.0 и 6.0 позволяет разработчикам создавать проекты ActiveX DLL и ActiveX EXE. В языке VB.NET им соответствует проект Class Library. Нельзя сказать, что проекты Class Library полностью подобны проектам ActiveX EXE или ActiveX DLL. Но именно они позволяют создавать компоненты многократного использования. Большая часть существующих свойств ActiveX EXE реализована в самой среде .NET Framework. Например, .NET Framework поддерживает "настоящий" многопоточный режим, используемый приложениями Windows Form и DCOM.
В состав конструктора проектов Class Library входит средство Server Explorer и инструментальная панель, что обеспечивает все необходимые инструменты для быстрой разработки приложений (Rapid Application Development — RAD). Рассмотрим процесс создания библиотеки классов подробнее. Этот процесс иллюстрируется на рис. 6.2—6.8. Сгенерированный код, приведен в листинге 6.1. На рис. 6.2 показан первый этап процесса. В начальном окне Visual Studio.NET (Start Page) щелкните на кнопке New Project.
Рис. 6.1. Основные компоненты среды .NETFramework
c. 6.2. Начальное окно Visual Studio.NET
76
Глава 6. Создание проектов VB.NET
Появится диалоговое окно New Project, показанное на рис. 6.3. Выберите из списка этого окна шаблон Class Library и присвойте ему имя ClassLibraryProject.
l i i s j
Templates:
Proe j ct Types:
t S Visual Basic Protects i - Q Visual C# Protects О Visual C++ Protects ; C j Setup and Deployment Protects ffl C l Other Protects D Visual Studio Solutions
ей* Wnidows Appcilao tin
all Wndows ControlLb i rary : €| Web Web ServtieWeb Control Appcilao tin Lbrar, и
[A protect for creating ca lsses to use In other appc il ato i ns Name: | Ca l ssUbraryProe l ct Locato i n: j F:\Vs l ual Studo i Proe jctsV/BOotNetForOevdopersSamp TJ Browse.. Г AddtoSokjtlon
С doseSolution
Protect will be created at F:\..AVBDotNetPorDevelopers3ampleProtects\ClassLlbraryPT0)ect. «More.
Cancel
Help
Рис. 6.3. Создание проекта на основе шаблона Class Library
Щелкните правой кнопкой мыши на файле c l a s s l . v b в окне Solution Explorer и удалите его из проекта, выбрав соответствующую команду в контекстном меню (рис. 6.4). ClassUbruryProjoct Microsoft VisualBasic.NET[design] Clami.vn E»e Edit ye j w E'olect B"M Cebug look Wn jdow Hep l H % i- **! iW m i a S 1 Л "л % Л .
clasU .vrb |roelct) |S *;tacrtlaP «alne(CU iislb aryP Public Class С lass 1
Output
вви
3 В Щ ClaiillbraryProject i d References Assembrylnfo.vb
Task l i t
"Ready
Pue. 6.4. Удаление из создаваемого проекта файла classl. vb
После удаления файла c l a s s l . v b воспользуйтесь командой ProjectOAdd Component. Появится диалоговое окно, показанное на рис. 6.5. Присвойте новому компоненту класса имя Chapter6. Созданный новый компонент будет открыт в окне конструктора, как показано на рис. 6.6. Библиотеки классов
77
Add New Hem: ClassUbraryProjecl Categore i s: it- 'cJ LocalProe j ct Items
Tempa l tes: Wn idows Form Ca lss
Moduel-
Component User Control DataFom i Ca lss Wziard DataSet XML File XML Schema [A class for creating component; иягч the vsual designer Name:
| Chapter*
Open
Caned
|
Hdp
Puc. 6.5. Добавление к проекту нового компонента класса ClassLibraryProjecl - Microsoft Visual Besfc.NET [design] - Chaptcr6.vb (., FJe E* SS«» Eroject guM Cebug look glndow si: 11= * 5i | щ * ш i s о ? о fs i«° ж Start Page Chapter6.vb [Design] | **x 0 iI
To add components to your class, drag them from the Server Expo l rer ar Toob i o^ and use thi roperhe5 wn idow to set their properties. To create methods and everts for your class, click he> e *.o
3
;wi!ch to code yi?w.
Output
Tack List
Ready
Puc. 6.6. Конструктор компонентов Visual Studio.NET После добавления компонента к создаваемому проекту необходимо изменить корневое пространство имен проекта. Для этого откройте диалоговое окно Project Properties, показанное на рис. 6.7, щелкнув правой кнопкой мыши в окне Solution Explorer на имени проекта (в данном случае— C l a s s L i b r a r y P r o j e c t ) и выбрав из контекстного меню команду Properties. Введите какое-либо имя корневого пространства имен. И последнее: добавьте новый метод к созданному классу. Для этого дважды щелкните в окне конструктора и введите соответствующий код в появившемся окне (рис. 6.8).
78
Глава 6. Создание проектов VB.NET
ClasslibrarjProjecl Property Pages >~4lCommon Properte is • General Butt Reference Path Sharn ig D g ivn«er^.au Defautls ue ns 1[s
F:\Visual Studio Pro)ects\VBDotNetForDevelopers5ampleProjects\aas ClassLtoraryProject.vbproj OassUbraryProJect.dll
Caned
Apply
Help
Puc. 6.7. Окно свойств проекта
ClasslibraryProjec! - Microsoft Visual Besic.NET (design] - Chapter6,vb* File Edit Ve i w Protect guild uebug loots ffihdow ft* m щ, t . A* [m * i •- s i л % % ?%.
Start Page Chapteirj.vb [Desg i n]* Chapter6.vb» | 1^*Chapter6 (VBDotNetF or Developers) j j | *AddToPer For mant «Counter Public Class Chapter6 " ' " ~'~ Inherits Systern.CurnponentModel.Component ii k Public Sub AddToPerformanceC<x«i ter(r!yVdl amount As Integer) End Sub End class
Out.pijt Task L.S I' Ready Puc. 6.8. Добавление метода компонента
Программный код, сгенерированный в результате описанных действий, приведен в листинге 6.1. ЛИСТИНГ 6.1. Код, генерированный конструктором компонента 'Visual Studio.NET добавляет наследование 'из System.ComponentModel.Component Public Class Chapter6 I n h e r i t s System.ComponentModel.Component
Библиотеки классов
79
'Дескриптор #Region не является частью языка Visual Basic 'Он генерируется редактором и используется для 'сворачивания фрагмента кода #Region " Component Designer generated code " 'Следующий код используется дизайнером Public Overloads Sub New(Container As System. ComponentModel.IContainer) 'Вызов конструктора базового класса MyClass.New () 'Необходима поддержка Windows.Forms Container.Add(me) End Sub 'Следующие код используется приложением Public Overloads Sub New() MyBase.New() 'Этот вызов необходим конструктору InitializeComponent() 'Добавьте любые вызовы после InitializeComponent() End Sub 'Необходимо конструктору компонентов Private components As System.ComponentModel.Container 'ЗАМЕЧАНИЕ. Следующая процедура необходима конструктору компонентов 'Не используйте для ее изменения редактор кода <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent () •Chapter6 End Sub #End Region 'Добавьте после всех методов метку #End Region, 'которая используется для сворачивания фрагмента кода Public Sub AddToPerformanceCounter(ByVal amount As Integer) End Sub End Class Обратите внимание, как используются свойства наследования средой .NET Framework для обеспечения различных служб: конструктора (через наследование) и отладки (через свойства). Кроме этого, приведенный код наглядно демонстрирует, как с помощью наследования происходит интегрирование исходного кода и конструкторов в Visual Studio.NET. Создаваемый класс наследуется из System.ComponentModel .Component, т.е. предоставляются методы, которые позволяют среде .NET Framework управлять разрабатываемым компонентом.
Приложения Web Form Одна из целей разработки среды .NET Framework— возможность создания Webприложений на основе языка HTML. В 1996 году корпорацией Microsoft была представлена технология Active Server Pages (ASP), большая часть Web-приложений создавалась с 80
Глава 6. Создание проектов VB.NET
использованием стандарта Common Gateway Interface (CGI) в форме исполняемых программ, генерирующих динамический HTML. В ASP совмещены свойства статического языка HTML и сценариев. К сожалению, в подобной архитектуре на одной странице "смешивается" код представления и программный код, что вызывает определенные проблемы как в процессе разработки, так и при сопровождении. Для решения описанной проблемы в Visual Basic 6.0 были добавлены проекты WebClasses, которые, как оказалось, имели недостатки, связанные в основном с низкой масштабируемостью. В среду .NET Framework включена новая версия ASP — ASP.NET; в ней создан новый тип проекта Web Forms. В таких проектах можно использовать технологию "перетащить и опустить" для создания Windows-приложений на основе форм. Создаваемые Web-формы обычно связаны с элементами управления на стороне сервера. Сервер выполняет какие-либо свойства, методы и события гораздо чаще, чем клиент. Основное различие между Web Forms и Windows Forms состоит в том, что элементы управления Windows Forms связаны с пользовательским интерфейсом, a Web Forms генерируют код HTML, интерпретируемый броузером.
Создание приложения Web Form При создании нового приложения Web Form в Visual Studio.NET среда разработки возьмет на себя выполнение ряда необходимых действий. В первую очередь на сервере Internet Information Server (IIS) будет создано приложение ASP.NET, а также все требующиеся записи в метабазе IIS и необходимые папки. После этого создается заданная по умолчанию Web-форма, которая затем открывается в окне конструктора Web Form. Откройте начальную страницу Visual Studio.NET и щелкните на кнопке New Project. Появится диалоговое окно New Project. В списке шаблонов выберите Web Application и присвойте имя, показанное на рис. 6.9. Щелкните на кнопке ОК. Visual Studio.NET вместе с IIS создает записи в метабазе IIS, а также все файлы, необходимые для приложения Web Form. На рис. 6.10 показано окно состояния процесса создания.
Puc. 6.9. Создание приложения Web Form
Приложения Web Form
Puc. 6.10. Проект создается
81
Готовый проект будет открыт в ранее созданной начальной Web-форме (рис. 6.11). Выберите на панели инструментов элемент управления Label и перетащите его на ранее созданную Web-форму (рис. 6.12). VBDolNetForDevelopersWeb -
0! г tj V
Edtt Vfew Eroject &j«d
M i c r o s o f t Visual Dasic.NET [ d e s i g n ]
Jebug
Farmat
Tabje
Insert
F[am«!
WebF,. Iooh
W,
d O H
StwtPage WebForml^spK |
H
4
'
:
;
fr
;
*
X
!
Q
\
:
^
\
er : :
•
i
f
Toolbox
•.;; И '..["."..'.'.". ХЫ patjis у»..- are wtfiir-.q an is \r< ( i r k i sycur fiicd*) sna objects t.-vlO fc« • • • ; ; ' ! ] ! ; • ; ; * , • ) ; ' ! J u i r ^ g u d tjiing 'ibs^'ucs C» and у) .io;rdsK.!t!fi-. ! ! ! ! ! ! ! ; ; ! ! ;
• : : : : •
.
:
:
! ' " , * * ! .'. 1 To enable ffotM iay^jt.
!
;
;
i
••
•'.':':'•.
I f
•'.::.
: у
...
: J
..
[ Q Design "] В HTML Output
|
»
I
E l
1
Task List
Ready
I
'•>,
A
Л«с. 6.1/. Созданный проект в окне HTML-конструктора
VBDoN l etForDevetopereWeb Microsoft Visual Oasc i .NET [design] WebF... ,f-lfn|fX[ ТаЦс Insert Fcames Ed« Proe j ct Jfn l dow Toolk««
-»
Data
x| i _
4 • X _
__—«_—___
W e b Forms It
Pointer
A
Label
f
Sw TextBox •bj Button JS1 LiriWutton ^
ImageButton
Д
Hyperurk
i k ) ; s ; / U y ) w a d ' ^ f e ' ' - ' * " ' ' • ; " : ::
:
:
; ;.:: :
otloiti. as Ln a H.jfdf;n:w:f-^Jri-j riov4>'№n!), ••'..' .
» t y of И» О О С И в П Ю FbwUnrout
. . ••
•
1 3 DropDownUst :J3 Data's id ЁЭ lotBox . J 3 Datalist H
Pttc. 6.12. Добавление элемента управления Label на Web-форму
82
Глава 6. Создание проектов VB.NET
Web-форма с элементом управления Label показана на рис. 6.13. После создания формы и добавления элемента управления Label дважды щелкните мышью на странице. Появится окно для ввода кода события Page_Load данной формы (рис. 6.14). VBDotNetForDevetopersWeb - Microsoft Visual Basic.NET [design] - WebF., Edit
View
Project
guild
Gebug
L-Г e - ' Start Page WebForm.laspH* |
Format
Tab(s
'-I
Insert
Frames
lools
Window
1 3 B ! :=
Це1р
'• <•X:Q Ig
•в Р Q OLabelD • • a
В Design | В HTML Output
Task List
lieisdy"
Puc. 6.13. Элемент управления Label добавлен на Web-форму
VBOolNetForDcvclopcrsWcb Microsofl Vioua) Basic. NET [design] WebF.. File Edit Ve i w Project guild £ebug lools ЩЫот Це1р Start Page WebFtrel.aspiT Webforml.aspK.vb* ^ W e b F o r r o l (VBDotWrtForDgyglopgriV » | | а » Р а д г Load aassWebFoiinl Inherits System.Web.UtPage Protected WitliEvcnts L a b e l l As System.Web.UI.WebC«itrols.Label i[WE?b form KI f h Private Sub Page_Load(HyVal sender1As System.Object, "Put user roHf to initialfi'p the pafjs here ! LabellJext = "Hello World!!!!" r End Sub 1
s Sy
End Class
Output Task List Ready
CdlO
Рис. 6.14. Добавьте код
Приложения Web Form
83
Код события Page_Load формы приведен в листинге 6.2. Листинг 6.2. Код события Page_Load формы Public Class WebForml Inherits System.Web.UI.Page Protected WithEvents Labell As System.Web.UI.WebControls.Label #Region " Web Form Designer Generated Code " 'Этот вызов необходим конструктору Web-форм <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() End Sub Protected Sub Page_Init(ByVal Sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init 'ЗАМЕЧАНИЕ. Этот метод необходим конструктору 'Не используйте для его изменения редактор кода InitializeComponent() End Sub #End Region Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'Сюда добавьте пользовательский код инициализации страницы Labell.Text = "Hello World!!!!" End Sub End Class После выполнения всех действий, представленных на рис. 6.9-6.14, вы получите работающее Web-приложение Hello World. Обратите внимание, что при создании этой Webстраницы не пришлось блуждать в дебрях языка HTML и заниматься обработкой строк. Web-страница, создаваемая при выполнении приложения, показана на рис. 6.15. -Э hll|i://locdlhiisl/VBDi>tNetForDuviMniJKrsWeti/WfobFnrini. На
Ed*
Vim
Favortes
Took
Help
Addr
Hello Woridllll
Puc. 6.15. Web-страница Hello World!!!! в окне броузера
Код HTML, сгенерированный приложением, приведен в листинге 6.3. ЛИСТИНГ 6.3. Код приложения Hello World 84
Форма Web Form содержит также представление, с помощью которого можно просмотреть код HTML, созданный конструктором. Код HTML в Visual Studio.NET представлен в листинге 6.4. Листинг 6.4. Проект Web Form Hello World <%@ Page Language="vb'' A u t o E v e n t W i r e u p = " f a l s e " Codebehind="WebForml.aspx.vb" Inherits="VBDotNetForDevelopersWeb.WebForml"%> <meta name="GENERATOR" c o n t e n t = " M i c r o s o f t V i s u a l Studio.NET <meta name="CODE_LANGUAGE" c o n t e n t = " V i s u a l B a s i c 7.0"> <meta name=vs_targetSchema c o n t e n t = " I n t e r n e t E x p l o r e r 5.0">
Как видно из приведенного примера, в .NET Framework реализован более простой и гораздо более эффективный способ создания Web-приложений.
Элементы управления Web Form Разработчики .NET Framework расширили набор элементов управления ASP. Элементы управления ASP.NET Web Form позволяют разработчикам создавать собственные средства управления, генерирующие код HTML. На рис. 6.16 и 6.17 иллюстрируется процесс создания одного из элементов управления Web Form (в качестве примера воспользуемся приложением Hello World). Обратите внимание, что для создания этого типа проектов необходимо выполнить всего лишь два этапа.
Tempa l tes:
Proe j ct Types: £3 Vs iualBast Proe j cts
1 О Visual C# Protects '[•• £ ] Visual C++ Projects , G3 Setup and Deployment Projects • •_] Other Projects 1 H i Visual Studio Solutions
Windows Application
Class Library
Web Application
Web Service
Windows Control library
;
A project for creating controls to use in Web appc il ato i ns Name: | Sampe lWebConrtol Location: j F:\Vs i ual Studo i Proe j cts\VBDotNetfoD i evep jl ersSa4 i p J j Bi Г Add to Solution
С Close Solution
Project v& be created at F:\...\VBDotNetForDevelopersSarreleProjects\SampteWebControl. «More.
I
<Ж
I
Cancel
II
Help
Puc. 6.16. Выберите шаблон проекта Web Control Library
86
Глава 6. Создание проектов VB.NET
Visual Studio.NET откроет созданный проект в окне редактора кода. SampleWebCorrtrot - Microsoft Visual Basfc.NET [design] - WehCustomCo. : File Ed* Ve iw Proe j ct Bud i Eebug Toosl Hn i don fs ! - 1 \A % % * v 5t«r! Page WebCustomControl.vb* i>X |*JWebCmtomControl (SampleWebCorJ |U\(Declaratk>ns) jj -
I
m
p
o
r
t
s
S
y
s
t
I
m
p
o
r
t
s
S
y
s
t
1
<
I
T
i
P
D
e
o
u
l
o
h
|
h
G
i
E
n
3
d
P
e
d
r
a
e
t
u
r
E
E
n
d
n
r
S
e
n
d
.
t
C
o
l
p
e
y
t
l
o
n
U
(
"
T
e
{
0
}
:
u
s
t
o
m
.
t
W
r
l
M
I
t
e
x
i
)
n
t
M
o
d
e
l
—
—
x
t
W
"
e
m
e
n
.
e
I
<
s
(
p
.
C
e
s
f
m
b
y
"
b
s
o
e
t
(
e
A
b
C
W
r
a
W
t
(
p
b
)
b
C
.
,
C
u
s
t
o
m
o
n
t
r
o
l
I
.
W
e
b
C
U
C
o
n
t
r
a
l
l
r
u
n
a
t
=
s
e
r
y
e
r
x
/
l
u
{
0
}
:
W
e
b
C
u
o
p
s
t
o
m
C
o
n
t
r
o
l
l
l
o
n
t
r
o
l
s
.
W
e
b
C
o
n
t
r
o
l
g
,
t
a
s
B
e
C
a
A
s
t
e
g
t
r
o
r
y
(
"
A
p
p
e
a
r
a
n
c
e
~
)
,
D
e
f
a
u
l
t
V
a
e
(
"
"
)
>
P
r
e
r
t
y
[
T
e
x
t
]
O
«
•
c
y
V
x
t
t
t
u
t
a
l
=
V
V
a
a
l
l
u
u
e
S
i
n
g
)
e
t
r
p
u
n
t
e
e
e
u
S
r
t
S
t
)
d
.
.
t
o
i
-
x
m
m
t
S
n
r
P
1
s
t
_
E
\
•
t
l
I
\
s
_
d
;•;
o
a
s
B
R
; !
r
D
a
r
e
n
P
i
l
e
m
F
t
>
C
-
:
l
o
r
n
i
u
b
i
I
D
a
l
l
e
e
y
e
t
:
d
.
W
O
r
v
i
e
t
r
e
r
(
i
[
d
T
e
e
K
s
t
S
J
u
b
R
e
n
d
e
r
(
B
y
V
a
l
o
u
t
p
u
t
A
s
S
y
s
t
e
m
.
W
e
b
.
U
I
.
H
t
m
l
r
e
x
t
W
r
l
t
e
r
)
)
b
s
1 Output Task Us: Ready
-Г S: .,-•
Л<с. 6.17. Проект Web Form Control в окне редактора кода
Теперь можно вводить код. Сначала удалите те строки кода, которые не нужны в данном проекте. Код создаваемого проекта HelloWorld приведен в листинге 6.5. ЛИСТИНГ 6.5. Код проекта HelloWorld Web Form Control
Imports System.ComponentModel Imports System.Web.UI Imports System.Web.UI.WebControls Public Class HelloWorldWebControl Inherits Systern.Web.UI.WebControls.WebControl Protected Overrides Sub Render(ByVal output As Systern.Web.UI.HtmlTextWriter) Dim oTable As New Table() Dim oRow As New TableRow() Dim oCell As New TableCellO oCell.Text = "Hello World" oCell.BorderColor = system.Drawing.Color.Firebrick ocell.BorderStyle = BorderStyle.Solid oRow.Cells.Add(oCell) oTable.Rows.Add(oRow) oTable.RenderControl(output) End Sub End Class Приложения Web Form
87
Теперь необходимо проверить библиотеку Web Control. Для этого воспользуйтесь командой FileoAdd ProjectoExisting Project From Web (рис. 6.18). SdntpleWebCunlrul Microsoft Visual Bmic.NET [design] - WebCustorrtCo. Protect
File j Edit
guild
Eebug
Iools ttbdow rttlp
[ - n. - Щ - Щ j > Debug
Qpen flose ИЗ AddNealtem... Ш
AddExistlnsKem...
A&IProJect Open Solution... Close Solution tlscefcneous Files
»
SaveWebCustomControll.vb Orl+S Sa-Л! WebCustomControll.vb 4s... Advanced Save Options,..
Я SaveAl Source Control 0 Page Setup.,. m Erht... Recent Ee li s Recent Proe j cts Est
Qrl+Shft+S Ctr+ iP 1
Atl+Q
A _J Output Task List Ready II Lnl Рис. 6.18. Команда меню File&Add Project ^Existing Project From Web Появится диалоговое окно, показанное на рис. 6.19. Add Existing Project From Web Enter the UP! of the server that you want to add the project from: Hep l Puc. 6.19. Выберите Web-сервер
Введите URL-адрес Web-сервера (см. рис. 6.19), что позволит воспользоваться одним из проектов, существующих на данном сервере. Выберите проект Web Form, создание которого описано в предыдущем разделе. После этого откройте окно Solution Explorer, щелкните правой кнопкой мыши на имени вновь созданного проекта и из появившегося контекстного меню выберите команду Set as Startup Project. Теперь необходимо добавить ссылку к созданной библиотеке Web Control. Для этого откройте окно Solution Explorer, щелкните правой кнопкой мыши на ссылке проекта и из появившегося контекстного меню выберите команду Add Reference. Появится диалоговое окно Add Reference (рис. 6.20). Активизируйте в этом окне вкладку Projects, а затем выберите только что созданную библиотеку Web Control.
88
Глава 6. Создание проектов VB.NET
Add Reference •NET | CCCIProe j cts |
See l cted Components: Component Harris Sampe lWebControl
hype Proe j ct
I Source | F:\Vs iual Studo i Proe j cts\VBOot..
Cancel
Hep l
Puc. 6.20. Диалоговое окно Add Reference Далее необходимо добавить созданный элемент управления на панель инструментов. Щелкните правой кнопкой мыши на панели инструментов Toolbox и из появившегося контекстного меню выберите команду Customize Toolbox (или же воспользуйтесь командой меню Tools^Customize Toolbox). Появится диалоговое окно, показанное на рис. 6.21. Активизируйте вкладку .NET Framework Components и щелкните на кнопке Browse. С помощью стандартного окна Windows открытия файла в библиотеке элементов управления найдите файл с расширением . d l l и щелкните на кнопке Open. После этого вернитесь во вкладку .NET Framework Components, выделите в списке имя нужной библиотеки и щелкните на кнопке ОК. По умолчанию нужный файл с расширением . d l l находится в подкаталоге b i n созданной библиотеки Web Control. Customize Toolbox COM Components .NET FrameworkComponents | Name 0Fi>ncDialog 0GroupBox 0HelpProvlder 0H5crclBar 0 Hyperlink El Image 0 IrnageButton 0ImageUst 0 Label
j|
| Namespace |p«h 1 Last. :•*! System, Windows .Forms D:\WINNT\Mlcrosoft.NEnFr... 31291 System.Windows.Forms D:\WINNTiMicrosoft.NEnFr... 3/29/ SamdeWebCorrtrol F:\Visuai Studo ProiectsWB... D:\WINNT\Microsoft. NET\Fr... 31291 System. Windows .Forms System. Windows .Forms D:\WINNT\Microsoft.NET\Fr... 3/29/ System. Web .UI. WebControb D:\WINNHMicrosoft.NET\Fr... 3/29/ System.Web.UI.WebControts 0:\WINNHMicrosoft.NEHFr.,. 3/29/ System. Web.UI.WebContrds D:\WlNNT\Microsoft. NET\Fr... 3/25/ 5y stem. Windows .Forms D:\WINNHMicrosoft.NET\Fr... 3/29/ System. Windows .Forms D:\VrtNNT\Microsoft.NET\Fr... 3/29/ v
< HelteWoridWebControl Language: Language Neutral Version: 1.0.S12.!8460(Retail)
Puc. 6.21. Диалоговое окно Customize Toolbox
Приложения Web Form
89
Теперь перетащите созданный элемент управление на форму WebForm, как показано на рис. 6.22. VBOolNelFnrDewlopersWeb - Microsoft VisualBaslc.NET [design] - Webf. File Edit gew Proe j ct Ju»d Beouj Format Table Insert Frames I°d* Щткж
Шire! a Hi«• I di.Vtl s StartPageWebCusct^Conr •x Label':::: ::: s а , , " i, - ' njHello World|o . ; : .
D
Код HTML, полученный после добавления формы к проекту Web Form, представлен в листинге 6.6. ЛИСТИНГ 6.6. Код HTML проекта Web Form <%@ Page Language="vb" A u t o E v e n t W i r e u p = " f a l s e " Codebehind="WebForml.aspx.vb" Inherits="VBDotNetForDevelopersWeb.WebForml"%> <%@ R e g i s t e r T a g P r e f i x = " c c l " N a m e s p a c e = " S a i T i p l e W e b C o n t r o l " Assembly="SampleWebControl" %> <meta name=" GENERATOR" c o n t e n t = " M i c r o s o f t V i s u a l Studio.NET 7.0"> <meta name="CODE_LANGUAGE" c o n t e n t = " V i s u a l B a s i c 7.0"> <meta n a m e = v s _ d e f a u l t C l i e n t S c r i p t c o n t e n t = " J a v a S c r i p t " > <meta name=vs_targetSchema c o n t e n t = " I n t e r n e t E x p l o r e r 5.0">
При запуске проекта в броузере отобразится Web-страница (рис. 6.23), код которой приведен в листинге 6.7. "3 Mtp://localhPS(/VBDotNetForOcvetopersWeb/WebForm1. Fie Edit Ve iw Favorties Took Hep l Q Back - Q • jx) jjj) 'Jj g2 Personal Bar yD Search '•id.-,-, jjgj /locaftmtt/VBOotNetForDevclopersWeb/WebForiril.aipx У , ) . И So JUr JHello Woridj Hello World!!!!
Puc. 6.23. Созданный элемент управления Web Form в броузере ЛИСТИНГ 6.7. Код HTML, сгенерированный при запуске созданного проекта Web Form
<meta content="Microsoft Visual Studio.NET 7.0" name=GENERATOR> <meta content="Visual Basic 7.0" name=CODE_LANQUAGE> <meta content=JavaScript name=vs_defaultClientScript> <meta content="Internet Explorer 5.0" name=vs_targetSchema> Элементы управления Web Form представляют собой достаточно мощный механизм, позволяющий инкапсулировать пользовательский интерфейс HTML. Загрузите с Webузла www. w i l l i a m s p u b l i s h i n g . com еще один пример приложения Web Form. В этом приложении используется усовершенствованный (по сравнению с имевшимся к моменту написания книги) элемент управления Web Form. Приложения Web Form
91
Проекты Web Service Web-службы (Web Services) позволяют более полно использовать функциональные возможности локальной сети или Internet. Активизация этих сервисов обычно происходит с помощью HTTP Get, HTTP Post или, что бывает чаще всего, SOAP. VB.NET полностью поддерживает создание Web-служб. На рис. 6.24-6.27 иллюстрируется процесс создания простейшего проекта Web Service с именем Hello World. В этом проекте Web-службой возвращается объект в виде XML. Клиент со своей стороны может либо просто использовать XML, либо перестроить объект. Если клиентом является другое приложение .NET Framework, повторно создается объект на основе его XML-описания. В рассматриваемом примере возвращается простой объект. Далее в главе описывается приложение Windows Form, в котором будет использоваться созданный проект Web Service. Сначала необходимо создать проект Web Service. Для этого откройте начальную страницу Visual Studio.NET и щелкните на кнопке New Project. Из списка шаблонов диалогового окна New Project выберите npoeKTASP.NET Web Service, как показано на рис. 6.24.
Project Type*:
- сЗ Visual Basic Protects СЭ Visual с* Protects E j Visual C++ Projects C j Setup and Deployment Projects £3 Other Projects Ш Visual Studio Solutions
Tempa l tes: Windows Application
Class Lfcrary
Wndo w ! Control Library j
Web Application
Web Service Web Control Library
v
j A protect for creating Web services to use from other applications Name:
| VBDotNetForDevelopwsservlce
Location:
| httpj/localhost
С Add to Solution
(=" dose Solution
Project wfl be created at nttp://localhc^fVBDotNetForOeveloperfService. ¥Mor£
Help
Of.
Рис. 6.24. Выберите шаблон проекта Web Service Созданный проект Web Service, как и большая часть проектов Visual Studio.NET, будет открыт в окне конструктора. Web-служба, по существу, является библиотекой классов, которая может быть вызвана с помощью ХМ L-кода. В данном примере не будем использовать конструктор, поэтому дважды щелкните в окне конструктора, чтобы активизировать режим просмотра кода. Введите код нового класса (листинг 6.8). ЛИСТИНГ 6.8. Класс Helloworld Public Class Helloworld Public Hello As String = "Hello" Public World As String - "World" End Class Теперь следует добавить метод WebService. Введите код, показанный в листинге 6.9, в класс S e r v i c e l , заменив закомментированный метод HelloWorld.
92
Глава 6. Создание проектов VB.NET
Листинг 6.9. Web-метод SayHelloWorld <WebMetnod()> Public Function SayHelloWorld() As HelloWorld Return New HelloWorld() End Function Полный код проекта Web Service приведен в листинге 6.10. Листинг 6.10. Код проекта Web Service Imports System.Web.Services Public Glass Servicel Inherits System.Web.Services.WebService tRegion " Web Services Designer Generated Code " Public Sub New() MyBase.New() 'Этот вызов необходим конструктору InitializeComponent() 'Добавьте свой код инициализации после вызова InitializeComponent() End Sub 'Вызов необходим конструктору Private components As System.ComponentModel.Container 'ЗАМЕЧАНИЕ. Этот метод необходим конструктору 'Не используйте для его изменения редактор кода <System.Diagnostics. DebuggerStepThrough()> Private Sub InitializeComponent() components = New System.ComponentModel.Container() End Sub Overrides Sub Dispose() 'ЗАМЕЧАНИЕ. Этот метод необходим конструктору 'Не используйте для его изменения редактор кода End Sub #End ' ' ' ' '
Region ПРИМЕР WEB SERVICE Пример сервиса HelloWorld() возвращает строку Hello World. Сохраните проект и заново создайте Для тестирования сервиса проверьте, является ли файл .asmx начальным, затем нажмите клавишу
<WebMethod()> Public Function SayHelloWorld() As HelloWorld Return New HelloWorld() End Function End Class Public Class HelloWorld Public Hello As String = "Hello" Public World As String = "World" End Class Проекты Web Service
93
Сейчас попробуем проверить созданную Web-службу. Эту задачу существенно упрощает среда .NET Framework. Для этого достаточно открыть окно броузера и ввести URLадрес нужной службы или же запустить ее из Visual Studio.NET. В результате выполнения этих действий в окне броузера появится тестовая страница (рис. 6.25). Ц Senricel Web Service - Microsoft Internet Explorer File
EdK
View
Favorites
Tools
Help
Servicel
The foo l wn i g operao tins are supported. For a formaldefinition, pelase reve iw the S3.yH.eUoWp.rfd R in M dfiyabthe i esij meacdoempm uebnlicdlyato c:on suom le. default namespace before the Web Servc A WeibeSweerb vcie ulsb esl aenndXp MLi tsd.oW cumientthe in WS ebLSaenrvciXe Desm crp i to i naceLan age (o WS DiLu),etyo d sigu u l! d ie esnctrfib y these ecnada poe n i ts. Theon defautltihvn au l e ofW thD is namesM paLcena si "hestp p://tem psuerd.iortg /"u .nq tI siervhcig iehylsi re coam antsu thm si adbe uh tlsinasimm certanbtebem beW fore ebthSeerW m dylem pe unnd btefic iledyldtcho elr.faT ieesrp pciao cm aouad syefeidbthee vcie ebIneeds tS o b e u n q i u e d i e f r o m o t h e W e b S v e s t h a t u s n i g "htp://tempur.iorg/" (the defautl namespace). F oe rbASSePrN ETaW eb rN vc iam ese,sp thae erfo ap ute l rntya.m e aW ceeb cS anervcibeeacthrb a igatthrib eute W v.tc ie tribc u tesS'se cn esdpth T hesep ien ug te edsisi uaasn n a p p e i l d o t h e a l s t h a t c o n t a i e W e b S r v c i e m e t h o d s . B o l w c o d e exampel that sets the Namespace to "htp://mcirosoft.com/webservcies/": C# [WebService (Neanespece-^htti)://nticcoaoft.cottt/webservieea/") ] public c l a s s MyUebService { I / / implementation • i }•
V i s u a l
'
• '•
•
•
•
.
••
.
•
•
•
•
•
•
.
B a s i c . N E T
Public Class <We±»Service(Nearespace:-'thttp://inicro3o£t.coin/weba« 1 implementation End Class : :
For more details on XML namespaces and URIs, see the Namespaces in XML, W3O document httu://www.w3.urq/TR/REX-Kml-names;/. J For more details on WSDL, see the WSDL Specification hH;iJ.;/w(vw,w_3,.or(i/TjR/_pf.sd.!., 'I
I
Рис. 6.25. Тестирование созданной Web-службы
Для проверки созданного метода щелкните на ссылке SayHelloWorld. Верхняя часть тестовой страницы метода SayHelloWorld показана на рис. 6.26. Для тестирования созданного метода щелкните на кнопке Invoke. Выходные данные метода приведены на рис. 6.27. Обратите внимание, что возвращаемый класс преобразован в код XML. Это одно из фантастических свойств среды .NET Framework, которое позволяет осуществлять преобразование различных типов в XML без каких-либо дополнительных команд.
94
Глава 6. Создание проектов VB.NET
File Edit Ve iw Favorties Tods Hep l Click hg j .CE; f°rа compe l te list of operatfons SayHelloWorld Test To test, click the 'Invoke' button, SOAP The following is a sampe l SOAP request and response. The placeholders shown need to be replaced with actual values. POST /VBDotNetrorDevelopersService/Servicel.asmx HTTP/1.1 Hose: localhost Content-Type: text/xntl; charset-utf-e Content-Length: length SOJUPAction: "http://tempuri.org/3ayHelloWorId" . . • <soap:Envelope xtnins: xsi»"http://ив». w3 .org/2001/XKLSchema <SayHelloHorld xmln3""http://cewipuri.org/" /> .HTTP/1.1 200 OK Content-Type: text/xml; charset-utf-B Content—Length: length •csoap:Envelope xmlna: xsi""http://»»». »3. org/2001/XHLSchema <SayH«lloWorldResponse xmln3""http: //tetnpuri.org/"> <3ayHelloWorldReault> «trin«etring
Puc. 6.26. Тестовая страница SayHelloWorld 3 lil|i://lncdlhusUVBDotNelForDevel(ipBrsSi!rvii;B/Ser»icf1. Pie Edit Ve i w Favorites Toosl Hep l - Hello <World>Worid
Приложения Windows О сетевых возможностях среды .NET Framework писали и говорили достаточно много. Но и "обычные" приложения не оставлены в стороне. Вероятно вы, как разработчик, достаточно хорошо знакомы и с приложениями Windows, и со способами их создания в Visual Basic. Эти способы практически не изменились ни в VB.NET, ни в .NET Framework. В Windows Forms используются расширенные и дополненные концепции форм Visual Basic. Кроме этого, Windows Forms могут использоваться в любом из языков среды .NET. Эти обновленные формы обеспечивают множество новых функциональных свойств и возможностей "обычных" приложений. Новые возможности .NET Framework, например безопасность, распространение и контроль версий, позволяют значительно упростить процесс создания таких приложений. При создании Windows Forms активно используются все преимущества новых возможностей .NET Framework. Формы и элементы управления, как и остальные объекты оболочки, являются классами, свойства которых могут быть унаследованы и дополнены разработчиками. Благодаря делегатам значительно улучщена модель события. Управление различными событиями и элементами управления выполняется с помощью единственного обработчика событий. Для того чтобы обеспечить единство стиля и свойств создаваемых форм в одном приложении или в организации приложений, разработчики могут воспользоваться визуальным наследованием. В примере, иллюстрируемом на рис. 6.28—6.35, создается небольшое приложение Windows Form, в котором применяется проект Web Service из предыдущего примера. Итак, откройте начальную страницу Visual Studio.NET, щелкните на кнопке New Project и в списке шаблонов появившегося диалогового окна New Project выберите шаблон Windows Application. Присвойте создаваемому проекту имя, показанное на рис. 6.28. New Project Proe j ct Types: s iual Basc i Protects : Ci V • !• -£] VsiualC# Projects
i -Щ Visual C++Projects \ £ ] Setup and Deployment Projects ;B C ] Other Projects 1 CJ Visual Studio Solutions
Templates:
Windows Application
Class Library
Web Application
Web Service
Windows : Control Library
Web Control Ubrary
:V.;
A project for creating an application with a Windows user interface Name:
{SampleWlndcmsApplcation
Location:
| F:\visual Studio ProjectslVBDotNetForOevelooersSamp •»| j
С Add to SokjBon
Browse...
Close Solution
Project Mt be created at F:\..AV6DcWetFccT>»elocwsSarnpleffojects\SamptoWMowsApplcalion. H(Jp
Рис. 6.28. Выберите шаблон Windows Application
После создания проект откроется в окне конструктора Windows Form (рис. 6.29). Теперь следует добавить Web-ссылку. Процесс создания ссылки Web Reference в окне Solution Explorer проиллюстрирован на рис. 6.30.
96
Глава 6. Создание проектов VB.NET
SampteWS it dowsAp plication Microsoft Visual Basic.Nil ftlesi$»ii] Form.. Ffc E* Vim &OBct Sudd Qebug Fgrm* Ioote Wnidow H«ta I > Debug jp - t i a; Hi Ok* •51 I Я &| Start Ради Fortnl.vb [Design] |
Output
TeskList ~f
Ready"
A«c. 6.29. Приложение Windows, открытое в окне конструктора форм SampteWindowsApplication - Microsoft Visudt Basic.NFT[iieslgn3 form.. E*>
E*
№w
ProjKt
guU
СЫшд
loob
i i t a
уф
Ю • ttl' * • в | * * Л | « ' «• • # - ^ I ЮвЬид • I (# ft 1 [5 a a I E!
Forml.vb [ D e s i g n ] |
< • X
*У*^|УГД5.ет5*ГШ»-|>>№;т.1л<л>!.1.^.^?^^^ Q
i ш I »a
;
Щ Sokjflon 'SampfeWlndoWiAppkettoo1 (1 project) p - S I SampleWmdowsApplkatran *)Ass«j I
7h& bfowse? Ь*:\-;л you find and consume references on i.hi? Web. When browsing to Web pages that eont ъ я rfiscovf-r -,- jr;rs* гг-зйопг Its Web Services &\d D^v-Sob will &•:• Si-sted in trie v^ndow ' to the right:. Voucer: hnd H'cis* iJisfovefy pages at Web Service di'«;:t.Q?y sitiv? arid on Visuel b f V/eb -r-s-rvers.
Avaa l be l references:
Some Wt*b Service D
Web References on Local Web Server
Рис. 631. Диалоговое окно Add Web Reference (щелкните на ссылке Web References on Local Web Server)
'HI Hi ! Address: |ht^://tocalhost/VBOol:fJetForDevittopersSefvice/S*rv>cel.asmx7wsd
xm{ns:ss="http;//www.w3,org/200l/XML
itmlns:sO="http://tempuri.org/" targetNamsEpace="http://tempuri.org/" •••• - <s:schema a ttributoForrnDefault--"qualified" elsmsntForrnDefault- "qualified" targetNdrnespace-iittp://tempuri. - <s: element name-"Say Hello World"> <s:compiexType /> 5;eiernBnt>
Puc. 6.32. Выбор ранее созданной службы
98
Глава 6. Создание проектов VB.NET
После того как Visual Studio.NET проведет опрос локального Web-сервера, появится список служб, существующих на локальном компьютере. Выберите из списка имеющихся служб проект Web-службы, созданный в предыдущем примере (рис. 6.32). Щелкните на кнопке Add Reference, что позволит вернуться к создаваемому проекту. Окно с выбранной ссылкой показано на рис. 6.33. SamptewindBwsApplicatioi - Microsoft VisualBasic.NET [design] - Form... [.«. ilCjifXI FJe £d* Veiw froe j rt * i B*ug Iods Window )Ле1р 3P * & - с? Ш 91 fife № j .*» - <* •• Ш • Щ | й §t e t j S ill S j IS * 9 if « Fonnl.vb [Design] |
S --Q(B j ^W R ee frences j:•E o le cb*oR ste • i • > • Щ\ e f re.w . ap iВ•^3Servcie lncsem d *^jNS e rvbtce.vlb |QrjA s s e m y n l o f v . m.lvb
Output Task List Web refefenceupdate тапрйе.
Puc. 6.33. Visual Studio.NETпосле создания ссылки Теперь добавьте к форме два текстовых поля и кнопку (рис. 6.34). Дважды щелкните на кнопке и введите код из листинга 6.11. ЛИСТИНГ 6.11. Код события BtnCl±ck_Event Dim oHelloWorldWebService As New localhost.Servicel() Dim oHelloWorld As localhost.HelloWorld oHelloWorld = oHelloWorldWebService.SayHelloWorld txtHello.Text = oHelloWorld.Hello txtWorld.Text = oHelloWorld.World Результирующий код проекта приведен в листинге 6.12.
Приложения Windows
99
, v i u w NelForl>evc-lopi-i sWimlmOTAppKtdtton - Microsoft V K I M I B a t i t J d Idestan I - Г-фШ.уЬ I
File
E«
»ew ;6ro|ert,, ВиИ k
СеЬов
Ftfraat
Took
f>
Jp * Ы • У UP ' "> • • *•» • i
I 5J Sou l to i n VBOotfe i tForbeveo l peH
1Й |
1
Ш VBDolNetForDcveloper." f "
Г
Й- Ljob) B- 'JJjJ Web Referenc« 1 в в? tocahosl . jК i Ш ^efefencemap»j й
Standard ' "Щ Microsoft Sans Se~1 ^ ControlText " П
_
£&Д11 The text contahed in the control.
OutpU
. А' форме добавлена кнопка и два текстовых поля ЛИСТИНГ 6.12. Код проекта после ввода кода события BtnCall (для вызова Web Service)
Public Class Forml Inherits System.Windows.Forms.Form •Region " Windows Form Designer generated code " Public Sub New() MyBase.New() 'Этот вызов необходим конструктору InitializeComponent() 'Добавьте свой код инициализации после вызова InitializeComponentО End Sub Public Overrides Sub Dispose () MyBase.Dispose () If Not (components Is Nothing) Then components.Dispose() End If End Sub Private WithEvents txtHello As System.Windows.Forms.TextBox Private WithEvents txtWorld As System.Windows.Forms.TextBox Private WithEvents btnCall As System.Windows.Forms.Button Private components As System.ComponentModel.Container 'ЗАМЕЧАНИЕ. Этот метод необходим конструктору 100
Глава 6. Создание проектов VB.NET
'Не используйте для его изменения редактор кода <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() Me.txtHello = New System.Windows.Forms.TextBox Me.txtWorld = New System.Windows.Forms.TextBox Me.btnCall = New System.Windows.Forms-Button Me.SuspendLayout •txtHello Me.txtHello.Location = New System.Drawing.Point(96, 80) Me.txtHello.Name = "txtHello" Me.txtHello.Tablndex = 0 Me.txtHello.Text = "" 'txtWorld i Me.txtWorld.Location = New System.Drawing.Point(96, 112) Me.txtWorld.Name = "txtWorld" Me.txtWorld.Tablndex = 1 Me.txtWorld.Text = "" 'btnCall Me.btnCall.Location = New System.Drawing.Point(96, 144) Me.btnCall.Name = "btnCall" Me.btnCall.Size - New System.Drawing.Size(100, 23) Me.btnCall.Tablndex = 2 Me.btnCall.Text = "Call Web Service" f 'Forml t Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(294, 267) Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.btnCall, Me.txtWorld, Me.txtHello}) Me.Name = "Forml" Me.Text = "Hello World" Me.ResumeLayout(false) End Sub #End Region Private Sub btnCall_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCall.Click Dim oHelloWorldWebService As New localhost.Servicel() Dim oHelloWorld As localhost.HelloWorld oHelloWorld = OHelloWorldWebService.SayHelloWorld txtHello.Text = oHelloWorld.Hello txtWorld.Text - oHelloWorld.World End Sub End Class Загрузите созданное приложение и щелкните на кнопке Call Web Service для обращения к проекту Web-службы. Полученная форма должна иметь вид, как на рис. 6.35.
Приложения Windows
101
Приведенный пример предназначен исключительно для демонстрации основной идеи создания пользовательского интерфейса с помощью форм Windows. Следует также обратить внимание на то, насколько Visual Studio.NET и .NET Framework упрощают процесс использования Web-служб.
Я Hello World
Рис. 6.35. Приложение Windows Form после щелчка на кнопке
Элементы управления Windows Visual Basic, начиная с версии 5.0, предоставляет разработчикам возможность создавать собственные элементы управления. VB.NET, в свою очередь, значительно расширил возможности языка, включив поддержку всех элементов .NET Framework. В качестве примера рассмотрим процесс создания элемента управления Windows Hello World, представленный на рис. 6.36-6.41. Как обычно, начнем с начальной страницы Visual Studio.NET. Щелкните на кнопке New Project и в списке шаблонов появившегося диалогового окна New Project выберите Windows Control Library (рис. 6.36). New Project Tempa ltes:
Proe j ct Types: *Zi Vs iual Basc i Proe j cts {_) Vs iual C# Proe j cts !• О Visual C++ Protects ! - Ш Setup and Deployment Projects C j Other Projects • Visual Studio Solutions
j A project for creatn i g contros l to use In Wn idows appc il ato i ns Name: S j amptoWn i dowsControl ~~ Location: | F:\Vtajal Studo i Proe j ctsV/BDotNetf orDevefaprisSamp ; •>| ] Browsu.. О AddtoSokition
Close Solution
Project w! be created at F:\...\VBDotNetForDeveloper:5ampleProject5l5ampleWrdowsControl. *Mor6
I
I
J .
Cancel
Help
Puc. 6.36. Диалоговое окно New Project с выделенным шаблоном Windows Control Library
Создаваемый проект Windows Control Library откроется в окне конструктора (рис. 6.37). Как и Visual Basic 6.0, создадим элемент управления из нескольких элементов — добавим две кнопки (рис. 6.38).
102
Глава 6. Создание проектов VB.NET
SampleWindowsControl - Microsoft Visual Basic.NET [design] - UserConlr.. Ffc
Puc. 6.38. Добавьте две кнопки к разрабатываемому элементу управления
Элементы управления Windows
103
Дважды щелкните на одной из кнопок, что приведет к активизации окна кода, и введите код события и двух обработчиков событий, приведенный на рис. 6.39. SampleWlnimvsControl - Microsoft Visual Basic.NET [design] - UserConlr. И*
|и Public Class User Contrail Inherits System.Windows.Forms.UserConti Ы Public Event HeloWorMDisplayedO
•
Private Sub btnllello_rliclt(IJy Val sender As 5yitcm.Obiect, flyVal e As Syjtem.Evei btnHelo.Enabled = False btnHe«o.TeKt = "Hello" II btnWm«.Enabled • False Then Me-BaekCoior = SystemJ>rawing.Ciilor.Yellow RaiseEvent Hello World№played() Endlf End Sub
Private Sub DtnWorM_C>ck(ByVal sender As System.Ob|ect, ByVal e As Systi ni.Evt btnWorld.ElMbled = False DtnVVorkLText <= "World" If btnHelo.Enabled = False Then Me.BackColor = SystemJJrawine.Color.DarkNagenl a : RaiseEvent HdloWorldDisplayed() j Endir I End Sub End Class I
Output
Task UK
Ready
! Ln79
Coll
Chi
Puc. 6.39. Окно ввода кода создаваемого элемента управления
Код разрабатываемого элемента управления, полученный после выполнения описанных действий, приведен в листинге 6.13. ЛИСТИНГ 6.13. Код элемента управления
Public Class UserControll Inherits System.Windows.Forms.UserControl Public Event HelloWorldDisplayed() #Region " Windows Form Designer generated code " Public Sub New() MyBase.New() 'Этот вызов необходим конструктору InitializeComponent() 'Добавьте свой код инициализации после вызова InitializeComponent() End Sub Public Overrides Sub Disposed MyBase.Dispose() If Not (components Is Nothing) Then 104
Глава 6. Создание проектов VB.NET
components.Dispose() End If End Sub Private WithEvents btnHello As System.Windows.Forms.Button Private WithEvents btnWorld As System.Windows.Forms.Button Private components As System.ComponentModel.Container 'ЗАМЕЧАНИЕ. Этот метод необходим конструктору 'Не используйте для его изменения редактор кода <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() Me.btnWorld = New System.Windows.Forms.Button() Me.btnHello = New System.Windows.Forms.Button() Me.SuspendLayout() 'btnWorld i Me.btnWorld.Location = New System.Drawing.Point(40, 80) Me.btnWorld.Name = "btnWorld" Me.btnWorld.Tablndex = 1 Me.btnWorld.Text = "Click" 'btnHello i Me.btnHello.Location = New System.Drawing.Point(40, 40) Me.btnHello.Name = "btnHello" Me.btnHello.Tablndex = 0 Me.btnHello.Text = "Click" t 'UserControll Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.btnWorld, Me.btnHello}) Me.Name = "UserControll" Me.ResumeLayout(False) End Sub #End Region Private Sub btnHello_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHello.Click btnHello.Enabled = False btnHello.Text = "Hello" If btnWorld.Enabled = False Then Me.BackColor = System.Drawing.Color.Yellow RaiseEvent HelloWorldDisplayed() End If End Sub Private Sub btnWorld_Click (ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnWorld.Click btnWorld.Enabled = False btnWorld.Text = "World" If btnHello.Enabled = False Then Me.BackColor = System.Drawing.Color.DarkMagenta RaiseEvent HelloWorldDisplayed()
Элементы управления Windows
105
End I f End Sub End Class Далее необходимо протестировать созданный элемент управления. Для этого выполните те же действия, что и при тестировании ранее созданного элемента управления Web Control. Создайте форму приложения Windows и добавьте к ней новый элемент управления (рис. 6.40). Не забудьте установить свойства формы так, чтобы она загружалась при запуске приложения. j SampteWIndoiv?Application - Microsoft Visual Basic.NETjdesign] - Form.. E«e
Ed*
View
Efolect
Bid
й*и)
Famv*
Ioofe
Ф'Ш'&Ш9\1 4l Ш j « • г« '
output
UjeiCortroll.vb
4£nkm
tj*
^ Debug
FormI,vti[Oeslgn] FotmZ.vb[Duign]* |
< •
x :
9
rasit UK
Ready
Puc. 6.40. Форма Windows с созданным элементом управления
Теперь вам остается только запустить приложение и щелкнуть на каждой из кнопок. Внешний вид приложения после выполнения описанных действий показан на рис. 6.41. Этот пример достаточно тривиален. Но, несмотря на это, он позволяет получить некоторое представление о способах создания элементов управления с помощью включения. Включение представляет собой механизм многократного использования при наследовании одним объектом методов другого объекта. Следует заметить, что кроме указанного способа создания элементов управления Windows в VB.NET существует еще несколько.
Рис. 6.41. Внешний вид элемента управления после щелчка на кнопке
106
Глава 6. Создание проектов VB.NET
Службы Windows Новым для Visual Basic является многообещающая и перспективная возможность создания служб Windows. В качестве примера создан проект Windows Service, при запуске которого происходит запись данных о начале и окончании его работы в журнал регистрации событий. Создание проекта начнем с начальной страницы Visual Studio.NET. Щелкните на кнопке New Project и из списка диалогового окна New Project выберите шаблон Windows Service (рис. 6.42). New Project Tempa l tes:
Proe j ct Types; -<3| Vsiual Basc i Proe j cts
i - Q Visual СГ Protects !- C j Visual C++Projects --Р-Ч Setup and Deployment Pro|ects if: Cl Other Protects C l visual Studio Solutions
Щ
Console Application
Empyt Proe jct Em p yt)ectW ebxsin NewFod Pro E tig lP erroejctnI Aproe jctforcrean tigservciesforW nd iows Name: Locao tin: jSampleWhdowsSerwce
| F:\Vlsual Studio Projects\VBDotNetFotDevelopersSamp •*[
С Add to Solution
Browse,..
|
S Close Solution
Project will be created at F:\...\VBDotNftForDevelopers5amDleProjert^SampleWindowsService. Help
. Рис. 6.42. Создание проекта на основе шаблона Windows Service
Добавьте ссылку System.Configuration. I n s t a l l , а затем вставьте код листинга 6.14 в окно ввода кода создаваемого приложения. ЛИСТИНГ 6.14. Базовый код Windows Service
Public Class Servicel Inherits System.ServiceProcess.ServiceBase fRegion " Component Designer generated code " Public Sub New() MyBase.New() ,,.. 'Этот вызов необходим конструктору InitializeComponent() 'Добавьте свой код инициализации после вызова InitializeComponent() End Sub 'Основная точка входа процесса Shared Sub Main() Службы Windows
107
Dim ServicesToRun() As System.ServiceProcess.ServiceBase ' Несколько служб NT могут выполняться в одном процессе 1 Для добавления еще одной службы к этому процессу 1 добавьте второй объект службы в следующей строке ServicesToRun = New System.ServiceProcess.ServiceBase () (New Servicel, New MySecondUserService} ServicesToRun = New System.ServiceProcess.ServiceBase ()_ {New Servicel} System.ServiceProcess.ServiceBase.Run(ServicesToRun) End Sub Private components As System.ComponentModel.Container 'ЗАМЕЧАНИЕ. Этот метод необходим конструктору 'Не используйте для его изменения редактор кода <System.Diagnostics.DebuggerStepThrough()> Private Sub _ InitializeComponent() components = New System.ComponentModel.Container() Me.ServiceName = "Servicel" End Sub #End Region Protected Overrides Sub OnStart(ByVal args() As String) 'Добавьте код запуска службы Dim oEventLog As New EventLog("Application", "red-leader", _ "HelloWorldService") oEventLog.WriteEntry("Hello World Windows Server Started") End Sub Protected Overrides Sub OnStop() 'Добавьте код остановки службы Dim oEventLog As New EventLog("Application", "red-leader", "HelloWorldService") oEventLog.WriteEntry("Hello World Windows Server Stopped") End Sub End Class Public Class HelloWorldServicelnstaller Inherits Installer Private oServicelnstaller As Servicelnstaller Private oProcessInstaller As ServiceProcessInstaller Public Sub New() MyBase.New() oServicelnstaller = New Servicelnstaller() oProcessInstaller = New ServiceProcessInstaller() oProcessInstaller.Account = ServiceAccount.LocalSystem With oServicelnstaller .StartType = ServiceStartMode.Manual .ServiceName = "HelloWorldWindowsService" End With Installers.Add(oProcessInstaller)
108
Глава 6. Создание проектов VB.NET
Installers.Add(oServicelnstaller) End Sub End Class
Обратите внимание на то, что в листинге 6.14 используется класс инсталлятора. Это является необходимым условием для инсталляции созданного проекта в Windows. После добавления этого класса и компиляции проекта воспользуйтесь для его инсталляции инструментом командной строки I n s t a l l U t i l . ехе.
Консольные приложения Visual Basic в настоящее время позволяет создавать также консольные приложения. Они выполняются из командного окна, называемого также окном DOS. Как правило, консольные приложения используются для обслуживающих программ, или утилит. В качестве примера рассмотрим процесс создания консольного приложения Hello World, которое будет использоваться для считывания числа отображения строки H e l l o World. Щелкните на кнопке New Project в окне начальной страницы Visual Studio.NET и выберите из списка диалогового окна New Project шаблон Console Application (рис. 6.43).
Proe j ct Types:
Templates:
-:_i visual Basic Protects 1-Й visual C# Prolects - O Visual C++Protects \ Ш Setup and Deployment Prolects Ш p Other Prolects • LJ Visual Studio Solutions
Web Web Service Web Control Application Lbrary
Windows Service
Empty Protect
A proe jct For creatn ig a commandni-le appScao tin Name: j Sampo lConsoe lAppcileo tln Locato in: | F:\Vs iualStudo i Protects\VBOotNetForDtveo lpersS«mp ' 1! Browse., О Add to Solution С Close Solution Project wl be created at F:\...\V6rx>tNetForDevelct«rsSarnplePro|Kt!\Ssmpl«:on»teApplication. «More.
I
i
J.
Cancel
Help
Puc. 6.43. Создание консольного приложения на основе шаблона Console Application
Добавьте код листинга 6.15 в окно ввода кода разрабатываемого консольного приложения. ЛИСТИНГ 6.15. Код консольного приложения
Imports System.Console Module HelloWorldConsoleApplications Sub Main() Dim iNumberOfTimes As Integer Dim i As Integer iNumberOfTimes = System.Convert.Tolnt32(Read()) For i = 1 To iNumberOfTimes
Консольные приложения
109
WriteLine("Hello World' Next End Sub End Module
Резюме В настоящее время VB.NET позволяет создавать любые типы приложений, которые поддерживаются средой .NET Framework и могут потребоваться для создания масштабируемой и гибкой инфраструктуры. В приложениях вашему вниманию предлагается ряд примеров, которые выходят за рамки материала, изложенного в этой главе. Исходный код рассматриваемых в этой главе примеров можно найти на Web-узле по адресу: www.williamspublishing.com.
110
Глава 6. Создание проектов VB.NET
ГЛАВА 7 Типы данных и объектов В каждом приложении используется определенный тип данных. Поскольку .NET Framework является объектно-ориентированной средой, то типы, в свою очередь, являются объектами. Именно это и отличает язык VB.NET от предыдущих версий Visual Basic. Существующая спецификация единого языка (Common Language Specification — CLS) обеспечивает его интегра-
цию в среду .NET Framework, описывая способы создания новых типов данных и расширения языка. Кроме того, в каждом языке существует набор встроенных типов, которые соответствуют определенным типам среды. Например, строковый тип данных (String) в VB.NET соответствует классу System. S t r i n g , а целочисленный тип (Integer) — классу System. I n t 3 2 .
Типы в .NET Framework Среда .NET Framework поддерживает множество типов, что позволяет манипулировать данными и создавать определяемые пользователем типы данных. Все типы данных .NET Framework в настоящее время являются объектами, наследованными из класса System. Ob j e c t . Все типы данных, существующие в .NET Framework, разделены на две категории: численные и ссылочные типы данных.
Численные типы В предыдущих версиях Visual Basic существовали объекты и встроенные переменные. Встроенные переменные представляют собой ячейки памяти с определенным содержимым; язык, в свою очередь, предусматривает функции, позволяющие работать с этим содержимым. Объекты также представляют собой ячейки памяти, обработка которых происходит с помощью средств СОМ-модели и виртуальных таблиц. Обработка переменных и объектов осуществляется по-разному. Присвоение значения переменной в Visual Basic 6.0 происходит, например, следующим образом: SName = sFirstName
При этом содержимое ячейки s F i r s t N a m e копируется в ячейку sName. Следует заметить, что использование подобного выражения для объявления объектов приведет к тому, что объекты o S a l a r i e d E m p l o y e e и oEmployee будут ссылаться на один и тот же объект. В этом случае при изменении свойств одного из объектов (например, o S a l a r i e d E m p l o y e e . F i r s t N a m e ="НовоеЗначение" или oEmployee.FirstName = "НовоеЗначение", где НовоеЗначение — произвольное значение какого-либо свойства) произойдет изменение обоих объектов. Присвоение значения объектной переменной (т.е. переменной, которая является ссылкой на объект) в Visual Basic 6.0 происходит следующим образом: Set oSalariedEmployee = oEmployee В отличие от этого, любые элементы .NET Framework являются объектами. Это нововведение потребовало изменить объекты или, другими словами, принципы их работы. В противном случае простые присвоения работали бы точно так же, как и объектные. Для того чтобы выйти из этого положения, в среде .NET Framework введено понятие численных типов. Численные типы {value types) представляют собой специальную форму объекта, которая наследует свойства класса System. ValueType, обеспечивающего присвоение значений. Присвоение значений объектам численных типов происходит точно так же, как и встроенным переменным в предыдущих версиях Visual Basic. Кроме того, численным типам присущи некоторые дополнительные возможности. Являясь объектами, все они обладают определенными свойствами, методами и событиями, позволяющими манипулировать объектом.
ПеременныеBoolean Булевы (или логические) переменные представляют собой базовый тип данных, который может принимать только одно из значений: истина или ложь (True или F a l s e ) . В среде .NET Framework данные типа Boolean являются объектами и обладают определенными методами, позволяющими манипулировать типом. В основном это методы преобразования, используемые для конвертирования данных типа Boolean в строковые, целочисленные или другие типы данных. В Visual Basic версий 5.0 или 6.0 для преобразования данных типа Boolean в данные, например, строкового типа используется функция CSTR, синтаксис которой приведен в следующем примере: sFlag = CSTR(bFlag)
В VB.NET для подобных целей можно обратиться к синтаксису предыдущих версий или использовать объектно-ориентированную версию языка: SFlag = bFlag.ToString ()
Целочисленные типы Одним из наиболее часто используемых типов переменных является целочисленный. В предыдущих версиях Visual Basic к целым числам были отнесены все целые числа из диапазона -32 768-32 767. В VB.NET этот диапазон был увеличен на несколько порядков. Теперь к данным типа I n t e g e r относятся все целые числа в диапазоне -2 147 483 6482 147 483 647. Кроме этого, существует несколько вариантов типа I n t e g e r , которые также относятся к численным типам: S h o r t , Long и Byte. Тип I n t e g e r , как и Boolean, обладает определенными методами, которые используются для обработки данных. Кроме того, тип данных I n t e g e r содержит метод Format, позволяю-
112
Глава 7. Типы данных и объектов
щий заменить функцию Format, используемую в предыдущих версиях Visual Basic. Функция Format в языках Visual Basic 6.0 и VB.NET имеет соответственно следующий вид: SFormatedNumber = F o r m a t ( i N u m b e r , " $ # # , # # # " ) SFormatedNumber = i N u m b e r . F o r m a t ( " $ # # , # # # " )
Тип чисел с плавающей запятой При выполнении точных математических операций в VB.NET используются тип чисел с плавающей запятой ( F l o a t i n g P o i n t ) и десятичный тип (Decimal), которые также принадлежат к численным типам. В языке VB.NET к этим типам относятся S i n g l e и Double F l o a t i n g P o i n t , а также тип Decimal, который используется вместо Currency. Указанные типы данных подобно Boolean и I n t e g e r обладают методами, которые позволяют манипулировать числовыми значениями.
Преобразование типов Все численные типы поддерживают метод ToString, который позволяет преобразовывать числовые значения в данные строкового типа. Но для выполнения преобразований другого рода (строка — целое число, строка — дата, целое число — логическая переменная и т.д.) следует воспользоваться специальными функциями Visual Basic, к которым относятся, например, CSTR, CINT, CLNG. Кроме этого, можно обратиться к классу System. Convert, в котором существует множество методов, используемых для подобных целей (гораздо больше, чем может предложить Visual Basic). Существует еще одна новая функция преобразования, с которой следует познакомиться поближе, — CTYPE. Эта функция используется для приведения объекта какоголибо типа к другому типу данных. В последующих главах книги вы не раз встретитесь с различными примерами использования функции CTYPE, синтаксис которой имеет следующий вид: CTYPE(ObjectToCase,TypeToCastTo)
Типы, определяемые пользователем Предыдущие версии Visual Basic позволяли создавать определяемые пользователем типы, состоящие из совокупности различных типов данных, объединенных с целью представления какого-либо типа данных. Пример определяемого пользователем типа в Visual Basic 6.0 приведен в листинге 7.1. Листинг 7.1. Определяемый пользователем тип в Visual Basic 6 Public Type Person FirstName as String LastName as String ID as Integer End Type Аналогичной возможностью обладает и VB.NET. Единственным отличием является использование ключевого слова S t r u c t u r e вместо Туре. Не забывайте о том, что S t r u c t u r e также относится к численным типам. В листинге 7.2 приведен пример определяемого пользователем типа в VB.NET. Листинг 7.2. Определяемый пользователем тип в VB.NET Public Structure Person Public FirstName as String Типы в .NET Framework
113
Public LastName as String Public ID as Integer End Structure
Ссылочный тип данных Ссылочный тип, в отличие от численных типов, не содержит никаких числовых данных. Вместо этого данные ссылочного типа указывают на какой-либо объект, другими словами, содержат адрес этого объекта в памяти. Когда вы присваиваете ссылочный тип другой переменной, происходит копирование только ссылки на объект. В результате две совершенно разные переменные могут указывать на один и тот же объект. Обработка данных ссылочного типа напоминает обработку объектных переменных в предыдущих версиях Visual Basic. Преобладающее большинство типов .NET Framework являются ссылочными. Ниже приведены основные ссылочные типы: •
тип Object (Объект);
• тип String (Строковый); • •
делегаты; массивы;
• интерфейсы; • тип Class (Класс).
Тип Object Тип O b j e c t является базовым, из которого наследуются все ссылочные типы данных. Это означает, что объекту может быть присвоен любой тип. Подобные функциональные возможности, с точки зрения разработчика Visual Basic, делают тип Ob j e c t эквивалентом типа данных V a r i a n t , который активно применялся в предыдущих версиях языка. Для создания определяемого пользователем ссылочного типа данных разработчиками используется тип С1 a s s.
Делегаты Делегат является специальным ссылочным типом, позволяющим создавать безопасный с точки зрения типов указатель на функцию. В среде .NET Framework делегаты являются ключевыми элементами в моделях события и многопоточной обработки.
Обработка строк С ростом Internet появилась потребность в строковой обработке, которая в Visual Basic не поддерживается в полном объеме. Visual Basic содержит библиотеку функций, используемых для обработки строк, которая, к сожалению, не позволяет полностью удовлетворить все потребности Internet-приложений на основе HTML. Опытные программисты разрабатывали методы, позволяющие обойти это ограничение, но зачастую подобные попытки приводили к созданию большого объема кода (что, безусловно, сказывалось на эффективности работы). Код Visual Basic 6.0 (с использованием модели ADO) для создания HTML-таблицы приведен в листинге 7.3. Листинг 7.3. Обработка строк для создания HTML-таблицы в Visual Basic 6.0 Private Function BuildHTMLTable(ByVal statsRecordset As ADODB.Recordset) As String 114
Глава 7. Типы данных и объектов
Dim sHTMLTable As String Dim IMaxLength As Long Dim iFields As Integer Dim iRecordCount As Integer Dim lCurrentPos As Long Dim sFieldValue As String 'Определение максимального размера строки IMaxLength = Len ("") iRecordCount = statsRecordset.RecordCount For iFields = 0 To statsRecordset.Fields.Count - 1 iMaxLength = iMaxLength + (statsRecordset.Fields(iFields).DefinedSize * iRecordCount) Next sHTMLTable = Space(iMaxLength) Mid(SHTMLTable, 0, 7) = "
" lCurrentPost = 6 Do Until statsRecordset.EOF Mid(sHTMLTable, lCurrentPos, 8) = "
Библиотека базовых классов .NET Framework предоставляет большие функциональные возможности для обработки строк в System. String (который в VB.NET является эквивалентом встроенного класса String) и System. Text. StringBuilder.
Класс System.String В среде .NET Framework встроенный класс S t r i n g фактически является синонимом класса System. S t r i n g . (Здесь и далее используется слово S t r i n g . ) Этот класс обладает гораздо большими функциональными возможностями, чем встроенный класс S t r i n g языка Visual Basic 6.0. Класс S t r i n g содержит дополнительные методы, используемые для обработки тех объектов, которые не могут быть обработаны средствами Visual Basic 6.0. Типы в .NET Framework
115
Концепция неизменяемого объекта очень важна для правильного понимания класса S t r i n g среды .NET Framework (подобное понятие существует также и в Visual Basic6.0). "Неизменяемый по отношению к классу S t r i n g " означает, что фактическая строка, находящаяся внутри класса, не может быть изменена. Услышав это, разработчики сразу же спрашивают: "Если строка не может быть изменена, то почему же работает код, приведенный в листинге 7.4?" На этот вопрос существует достаточно простой ответ, позволяющий также объяснить, почему эта программа медленно работает в Visual Basic 6.0, VB.NET и С#. Когда происходит конкатенация, или связывание строк, CLR фактически остается "за сценой", создавая в это время новые строковые буфера для хранения соединенных вместе строк (рис. 7.1). Dim sString as String sString = "Hello World" ШаП sString = «String &"" & sString & "" & sString Шаг 2
Hello World Hello World (длина = 23) ШагЗ
Hello World Hello World (длина = 24) Шаг 4
Hello World Hello World Hello World (длина = 35) Шаг 5
MsgBox(sString) Рис. 7.1. Механизм связывания строк в CLR 1. CLR создает строковый буфер, величина которого достаточна для хранения строки H e l l o World. Строковый объект содержит ссылку на этот буфер. 2. CLR создает строковый буфер, величина которого достаточна для хранения строки H e l l o World и первой односимвольной пустой строки. Строковое значение и пустая односимвольная строка копируются в новый буфер. Ссылка указывает на новый буфер. 3. CLR создает строковый буфер, величина которого достаточна для хранения предыдущей строки и строки H e l l o World. Прежняя строка и строка H e l l o World копируются в новый буфер. Измененная ссылка указывает на новый буфер. 4. CLR создает строковый буфер, величина которого достаточна для хранения предыдущей строки и второй односимвольной пустой строки. Строковое значение и 116
Глава 7. Типы данных и объектов
пустая односимвольная строка копируются в новый буфер. Измененная ссылка указывает на новый буфер. 5. CLR создает строковый буфер, величина которого достаточна для хранения предыдущей строки и строки H e l l o World. Прежняя строка и строка H e l l o World копируются в новый буфер. Измененная ссылка указывает на новый буфер. 6. Функция MsgBox отображает содержимое строки, которая находится в буфере. Листинг 7.4. Конкатенация строки Dim sString as sString sString = "Hello World" sString - sString & " " & sString & " " & sString MsgBox(sString) 'Отображает "Hello World Hello World Hello World" Как видно из приведенного кода, для выполнения простейшей строковой обработки среда CLR должна проделать большой объем работы. Обратите внимание, что выше описан упрощенный цикл конкатенации в Visual Basic 6.0. В классе S t r i n g появился дополнительный метод ConCat, позволяющий упростить процесс конкатенации строк (по крайней мере, для рассмотренного сценария). В листинге 7.5 приведен пример использования метода ConCat для решения задачи, выполняемой программным кодом листинга 7.4. Листинг 7.5. Метод ConCat Public Sub UseConcatO Dim sString as String sString = "Hello World" sString = System.String.ConCat(sString," ", sString, " ", sString) MsgBox(sString) End Sub Приведенный код выполняется намного эффективнее. Это связано с тем, что при использовании метода ConCat среда CLR в первую очередь вычисляет требуемую величину строкового буфера. После этого CLR копирует все символы в буфер. В классе S t r i n g существует также множество других методов, позволяющих выполнять обработку строк. К числу новых функциональных возможностей, которые обеспечиваются этими методами, можно отнести следующее: •
свойства символьного типа Chars позволяют выполнять итерацию символов строки;
•
методы S t a r t s W i t h и EndsWith позволяют проверить наличие данной строки соответственно в начале или в конце строки;
•
метод Remove может использоваться для удаления определенного числа символов в данной позиции;
•
методы PadLeft и PadRight могут использоваться для заполнения символами пустого пространства с левой или правой стороны строки. Вернемся к проблеме конкатенации строк, решение которой приведено в листинге 7.5. Этот метод позволяет справиться только с некоторыми достаточно простыми сценариями строковой обработки, но для решения проблемы, представленной в листинге 7.3, в .NET Framework используется уже другой класс.
Класс SystemTextStringBuilder Библиотека базовых классов .NET Framework дополнена новыми функциональными возможностями, позволяющими более эффективно создавать длинные строки. Эти возможности обеспечиваются классом System. T e x t . S t r i n g B u i l d e r . Для создания Типы в .NET Framework
117
HTML-таблицы использовался код, приведенный в листинге 7.3. Эта задача может быть с успехом решена с помощью кода листинга 7.6, в котором используются модель ADO (объект RecordSet) и класс System. T e x t . S t r i n g B u i l d e r . Листинг 7.6. Использование класса StringBuilder для формирования строки Private Function BuildHTMLTable(ByRef statsRecordset As _ ADODB.Recordset)As String Dim sHTMLTable As New System. Text. StringBuilder ,() sHTMLTable.Append("
Пакетирование и распаковка Иногда приходится интерпретировать численный тип данных как ссылочный или наоборот. Эта задача может быть решена с помощью технологий, известных как пакетирование и распаковка. Пакетирование (boxing) позволяет создавать ссылочный тип из численного. Распаковка (unboxing) используется для создания численного типа из ссылочного. Общая спецификация типов определяет соответствующий ссылочный тип для каждого из численных типов. Эти типы носят название Boxed Types. Процесс создания Boxed Types в VB.NET, как показано в листинге 7.7, достаточно прост. ЛИСТИНГ 7.7. Пакетирование
Dim ilntegerValue as Integer Dim iBoxedlnteger as Object ilntegerValue = 5 iBoxedlnteger = ilntegerValue Распаковка представляет собой действие, обратное пакетированию. Следует заметить, что далеко не все ссылочные типы имеют соответствующие численные типы, поэтому распаковка подобных типов невозможна. Синтаксис процесса распаковки ссылочного типа в VB.NET приведен в листинге 7.8. Он настолько же прост, как и синтаксис пакетирования. Листинг 7.8. Распаковка Dim ilntegerValue as Integer Dim iBoxedlnteger as Object Dim iUnBoxedValue as Integer ilntegerValue = 5 iBoxedValue = ilntegerValue iUnBoxedVale = CType(iBoxedValue,Integer) 118
Глава 7. Типы данных и объектов
Обратите внимание, что в случае несоответствия типов этот код не будет работать должным образом. Это может произойти, например, при попытке функции СТуре преобразовать ссылочный тип в какой-либо другой, отличный от типа I n t e g e r .
Встроенные типы данных в VB.NET Все языки, поддерживающие .NET Framework, без каких-либо ограничений поддерживают набор базовых или встроенных типов данных, которые соответствуют типам .NET Framework. Набор типов VB.NET приведен в табл. 7.1. Таблица 7.1. Встроенные типы данных VB.NET Тип
Размер в байтах
Boolean Byte Char Date Decimal Double Integer Long Object Short Single String
Класс .NET Framework
Тип Visual Basic 6.0
4
System.Boolean
Boolean
1
System.Byte
Byte Char
2
System.Char
8
System.DateTime
Date
12
System.Decimal
Currency
8
System.Double
Double
4
System.Int32
Long
8
System.Int64
отсутствует
4
S y s t e m . O b j e c t (класс)
Object
2
System.Intl6
Integer
3
System.Single
Single
10+(две длины строки)
System.String
Определяемый пользовате- Сумма размеров его членов Наследуется из System.ValueType лем тип (структура)
String Type
Visual Basic для выполнения перекрестной языковой интеграции должен быть простым языком. Поэтому некоторые типы данных были осознанно оставлены без поддержки VB.NET. Некоторые из .NET-языков могут создавать типы, которые не поддерживаются другими .NET-языками. VB.NET разработан только для поддержки встроенных типов данных, описываемых в общей спецификации типов. Таким образом, эта версия языка не поддерживает следующие типы: •
типы без знака (внутренние переменные могут быть типами как беззнаковые);
•
оператор перегрузки.
Тип Date В Visual Basic 6.0 для хранения данных типа Date требуется четыре байта. Этот тип практически не отличается от типа Double. В VB.NET тип Date использует тип данных DateTime оболочки .NET Framework. В настоящее время DateTime представляет собой целое восьмибайтовое число. Изменение величины данных привело к невозможности автоматического преобразования типов Date и Double в языке VB.NET, но существующие Встроенные типы данных в VB.NET
119
методы System.Convert.ToDouble и System.Convert.ToDateTime позволяют преобразовывать данные типа DateTime в данные типа Double и обратно.
Тип Decimal Тип данных Currency, существовавший в предыдущих версиях Visual Basic, в языке VB.NET не поддерживается. Поэтому был введен тип данных Decimal, обеспечивающий те же функциональные возможности, что и Currency. Этот тип данных позволяет выполнять математические операции с гораздо большей точностью.
Типы Short, Integer, Long По всей вероятности, изменение типов данных в VB.NET повлечет за собой изменение типов I n t e g e r и Long. В Visual Basic 6.0 тип данных I n t e g e r представлял собой 16битовое целое число, а тип данных Long — 32-битовое целое число. В VB.NET новый тип данных S h o r t является 16-битовым целым числом, I n t e g e r теперь представляет собой 32-битовое целое число, a Long — 64-битовое целое число. Такое существенное изменение может послужить причиной многих проблем, возникающих при переносе кода из Visual Basic 6.0 в VB.NET, особенно при обращениях к функциям Win32 API.
Тип Object В языке VB.NET более не существует типа данных Variant, позволяющего содержать данные любых типов. Все элементы .NET Framework являются объеьстами, поэтому в VB.NET создан тип данных Object, используемый для тех же целей, что и Variant в предыдущих версиях Visual Basic. Обратите внимание, что для этого типа не сущесгвует каких-либо ограничений по созданию ссылок на простые типы данных, такие, например, как I n t e g e r .
Тип String Одним из наиболее важных типов данных в Visual Basic является S t r i n g . К сожалению, именно с этим типом связана большая часть проблем, возникающих в процессе конкатенации строк. В VB.NET тип данных S t r i n g более не поддерживает строки фиксированной длины. В среде .NET Framework длина любой строки является переменной величиной и определяется ее содержимым. В предыдущих версиях Visual Basic конкатенация строк представляла собой наиболее сложную часть программирования. Теперь с этой задачей успешно справляется VB.NET.
Тип Char В VB.NET появился новый встроенный тип данных, используемый для обработки Unicode-строк. Тип Char представляет собой 16-битовое числовое значение, используемое для хранения одного Unicode-символа. Переменные Char могут быть преобразованы в численные типы только явным образом.
Тип Class Тип C l a s s является ключевым в процессе создания объектно-ориентированных систем. Возможность построения классов в языке Visual Basic существовала еще с версии 4.0. 120
Глава 7. Типы данных и объектов
В среде VB.NET, в свою очередь, используются возможности, присущие всем предыдущим версиям языка. Тип C l a s s является ссылочным и содержит элементы трех типов: элементы данных, элементы функций и вложенные типы. Элементы данных доступны непосредственно через типы данных или свойства. Элементы функций в большинстве случаев используются для обработки данных, которые содержатся в элементах данных. Кроме этого, в VB.NET появилась новая возможность — способность создавать дочерний класс непосредственно в классе. Класс, созданный подобным образом, называется вложенным типом (nested type). В предыдущих версиях Visual Basic каждый класс содержался в отдельном .CLS-файле. В VB.NET существует уже несколько способов организации классов. Классы могут быть размещены в отдельных файлах, в одном и том же файле, а также в любых возможных комбинациях. Для создания иерархии объектов в предыдущих версиях Visual Basic классы создавались без явной связи. С помощью кода листингов 7.9-7.11 можно получить представление об общих и отличительных чертах иерархии объектов в Visual Basic и VB.NET. В листинге 7.9 представлен класс Visual Basic 6.0, который называется COrder; одному из свойств этого класса присвоено имя C l i n e l t e m . ЛИСТИНГ 7.9. Файл COrder. CLS Private m_10rderNumber as long Private m_oLineItem as Clineltem Public Property Get LinelteraO as Clineltem Set Lineltem = m_oLineItem End Property Public Property Get OrderNumber() as Long OrderNumber = m_10rderNumber End Property Public Property Let OrderNumber(ByVal RHS as Long) m.OrderNumber = RHS End Property В листинге 7.10 приведен код класса Visual Basic 6.0, который называется C l i n e l t e m ; этот класс также обладает некоторыми свойствами. Следует заметить, что между этими классами явно определенной связи не существует. ЛИСТИНГ 7.10.
Файл Clineltem. CLS
Private m_lProductCode as Long Private m_sProductDescription as String Public Property Get ProductCode () as Long ProductCode = m_lProductCode End Property Public Property Let ProductCode (ByVal RHS as Long) m_lProductCode = RHS End Property Public Property Get ProductDescription () as Long ProductDescription = m_sProductDescription End Property
Встроенные типы данных в VB.NET
121
Public Property Let ProductDescription (ByVal RHS as Long) m_sProductDescription = RHS End Property
В VB.NET связь между классами может быть создана непосредственно в структуре класса. В листинге 7.11 приведен код класса COrder, содержащий вложенный тип Clineltem. Листинг 7.11. Субкласс в VB.NET Public Class COrder Private c_10rderNumber as long Private c_oLineItem as New Clineltem() Public Readonly Property LineltemO As Clineltem Get Return c_oLineItem End Get End Property Public Property OrderNumber as long Get OrderNumber = c_10rderNumber End Get Set (ByVal Value as Long) c_lOrderNumber = value End Set End Property Public Class Clineltem Private c_lProductCode as Long Private c_sProductDescription as String Friend Sub New() MyBase.New() End Sub Public Property ProductCode as Long Get ProductCode = c_lProductCode End Get Set(ByVal Value as Long) c_lProductCode - value End Set End Property Public Property ProductDescription as String Get ProductDescription = c_sProductDescription End Get Set (ByVal Value as String) c_sProductDescription = value End~Set End Property End Class End Class 122
Глава 7. Типы данных и объектов
Структуры В предыдущих версиях Visual Basic существовала возможность создания определяемых пользователем типов данных {User Defined Data Types, или UDT) с помощью оператора Туре. Определяемый пользователем тип данных, как показано в листинге 7.12, представляет собой объединение нескольких различных типов в один тип данных. ЛИСТИНГ 7.12. ТИП Employee в Visual Basic 6.0
Public Type Employee FirstName as String LastName as String SocialSecurityNumber as String BirthDate as Date Dependents as Integer End Type В VB.NET, как показано в листинге 7.13, оператор Туре заменен оператором S t r u c t u r e . ЛИСТИНГ 7.13. Структура типа Employee в VB.NET
Public Structure Employee Public FirstName as String Public LastName as String Public SocialSecurityNumber as String Public BirthDate as Date Public Dependents as Integer End Structure Оператор S t r u c t u r e фактически создает численный тип. В действительности структуры представляют собой тип численного класса. В языке VB.NET структура содержит не только типы данных, но также свойства и методы. Как показано в листинге 7.14, все индивидуальные типы данных, за исключением поля S o c i a l S e c u r i t y N u m b e r , имеют общие модификаторы доступности. Все элементы структуры в языке VB.NET должны иметь модификатор доступности. В VB.NET появилась новая возможность, позволяющая ограничивать область доступа для отдельных элементов структуры. В предыдущих версиях Visual Basic подобной возможности для определяемых пользователем типов не существовало. Кроме этого, как показано в листинге 7.14, структуры могут иметь свойства и методы. На первый взгляд может показаться, что тип S t r u c t u r e практически ничем не отличается от класса. По многим показателям это действительно так, но в то же время имеется ряд существенных отличий. Листинг 7.14. Пример структуры Public Structure TEmployee Public FirstName as String Public LastName as String Private SocialSecurityNumber as String Public BirthDate as Date Public Dependents as Integer Readonly Property FullName Get Return FirstName & " " & LastName End Get End Property Структуры
123
Public Function CalculateExemptionAmount(ByVal _ AmountPerDependent as Decimal) as Decimal Return AmountPerDependent * Dependents End Function End Structure
Структуры размещены в памяти не как объекты, а как численные типы (к численным типам относятся встроенные типы данных, такие как I n t e g e r , Boolean и т.п.). Результатом этого является повышение эффективности их обработки и, как следствие, снижение затрат на "сборку мусора" и подобные операции. Поэтому эффективность структур гораздо выше. Структуры не могут наследоваться из класса или структуры; точно так же другая структура или класс не могут наследоваться из структуры. Кроме этого, структуры совершенно по-разному относятся к конструкторам и деструкторам. Пример класса, созданного при обращении оператора New к классу, приведен ниже. Dim oEmployee as New CEmployee Подобный метод не может использоваться при создании структуры. Это связано с тем, что структура, как и любые другие численные типы, не должна создаваться явно. Ниже приведен пример создания структуры. Dim tEmployee as TEmployee После того как структура создана, значения всех ее элементов приводятся к значениям по умолчанию, заданным .NET Framework. (Значения численных типов по умолчанию равны 0, строковых — пустой строке, значения типа Boolean равны F a l s e . ) Структуры могут содержать конструкторы, но в то же время не могут иметь конструктор, заданный по умолчанию. Это связано с тем, что среда .NET Framework создает для структуры один конструктор неявно. При этом структурам не разрешено иметь деструкторы. Как только переменная "выпадет" из области действия структуры или ей будет присвоено нулевое значение, CLR, используемая для поддержания эффективности структур, очистит область памяти, в которой размещена данная структура. Структуры, подобные классу Туре в Visual Basic 6.0, представляют собой достаточно полезный тип для создания простых структур данных и должны использоваться для тех же целей. Структуры не должны применяться для представления сложного объекта, а скорее, в качестве фрагмента данных с некоторыми простыми функциями.
Резюме Среда .NET Framework и, следовательно, VB.NET предоставляют множество новых возможностей, позволяющих создавать и использовать новые типы данных. Язык VB.NET был разработан, чтобы упростить процесс создания приложений и облегчить создание компонентов, которые могут быть использованы другими языками, поддерживающими .NET Framework. Новые объектно-ориентированные свойства языка VB.NET обеспечили классам Visual Basic невероятное разнообразие возможностей. Это относится и к простым определяемым пользователем типам. Более того, не только расширились объектно-ориентированные возможности Visual Basic, но и упростился процесс создания устойчивых иерархий объектов.
124
Глава 7. Типы данных и объектов
Управление порядком выполнения команд Во всех современных языках программирования существуют так называемые логические операторы, используемые для управления порядком выполнения команд. Visual Basic содержит набор структурированных и простых программных операторов, обладающих широкими возможностями для управления логическим процессом выполнения. В VB.NET немного "подчищен" базовый язык и удалены или изменены унаследованные неструктурированные операторы. Логические операторы могут быть сгруппированы по трем основным типам: операторы выбора, итерации и унаследованные конструкции.
Выражения с сокращенным циклом Прежде чем рассматривать типы логических операторов, существующих в языке VB.NET, следует познакомиться с его новыми возможностями. Обратите внимание, что до появления VB.NET выражения с сокращенным циклом языком Visual Basic не поддерживались. Выражения с сокращенным циклом представляют собой одну из новых возможностей, позволяющих повысить потенциальную эффективность языка. В том случае, если условным выражением является e v a l u a t e d , результат выражения может быть определен без оценки всех его частей. Затем оператор обходит данное выражение и завершает процесс без выполнения всего программного кода. Приведенный пример поможет разобраться в этом. В листинге 8.1 представлен фрагмент кода VB.NET, не поддерживающего выражения с сокращенным циклом.
Листинг 8.1. Представление выражений с сокращенным циклом Private Function EligibleForDependentBenefits(ByVal bEmployee as Boolean, ByVal SSN as String) as Boolean Dim bDependentBenefits as Boolean bDependentBenefits « bEmployee And EmployeeHasDependents(SSN) Return bDependentBenefits End Function Private Function EmployeeHasDependents(ByVal SSN as String) as Boolean 'Вызов хранимой процедуры End Function Как видите, условное выражение первой функции определено. Это выражение получает значение логической переменной Boolean и сравнивает его опять же со значением Boolean, возвращаемым функцией. Если оба значения истинны, переменной Boolean присваивается значение True. Если же значение Boolean ложно, происходит повторное обращение к функции. В описываемом примере функция вызывает хранимую процедуру (что является достаточно сложной операцией). Следует заметить, что особой необходимости в функции, которую лишь однажды придется вызвать, не существует. Для решения этой проблемы можно применить схему с сокращенным циклом. Для этого требуется последовательно оценить левую и правую части выражения. Обработка выражения, в котором содержится логический оператор And, происходит следующим образом. Если проверяемый элемент ложен, оставшаяся часть выражения не выполняется. Если же его значение истинно, происходит проверка следующей части выражения. Для создания выражения с сокращенным циклом в языке VB.NET необходимо воспользоваться "сокращенными" версиями логических операторов And и Or: AndAlso и OrElse. В листинге 8.2 представлен пример версии функции с сокращенным циклом, приведенной в листинге 8.1. Листинг 8.2. Выражение с сокращенным циклом Private Function EligibleForDependentBenefits(ByVal bEmployee as Boolean, ByVal SSN as String) as Boolean Dim bDependentBenefits as Boolean bDependentBenefits = bEmployee AndAlso_ EmployeeHasDependents(SSN) Return bDependentBenefits End Function Вызов хранимой процедуры произойдет только в том случае, если флаг элемента bEmployee истинен. Теперь, когда вы уже получили некоторое представление о выражениях с сокращенным циклом, пора перейти к языковым конструкциям, которые используются в большей части выражений.
Операторы выбора Используются для определения порядка выполнения команд. В языке VB.NET существует два типа операторов выбора: логические операторы IF и S e l e c t Case.
Оператор IF Наиболее распространенными и, пожалуй, самыми важными логическими операторами как в структурном, так и в объектно-ориентированном программировании являются операторы ветвления или, иначе говоря, операторы условного перехода. В языке Visual Basic они представлены условным оператором IF (рис. 8.1). 126
Глава 8. Управление порядком выполнения команд
Структура условного оператора IF в языке VB.NET приведена в листинге 8.3. Оператор ELSE IF, в свою очередь, приведен в листинге 8.4. Листинг 8.3. Условный оператор IF IF Boolean e x p r e s s i o n THEN Операторы, выполняющиеся, если булево выражение истинно ELSE Операторы, выполняющиеся, если булево выражение ложно END
IF
•
•
Листинг 8.4. Расширенный синтаксис оператора ELSEIF IF Boolean e x p r e s s i o n THEN Операторы, выполняющиеся, если булево выражение истинно ELSEIF Boolean e x p r e s s i o n THEN Операторы, выполняющиеся, если булево выражение истинно ELSE Операторы, выполняющиеся, если булево выражение ложно END IF На первый взгляд может показаться, что условный оператор IF в языке VB.NET практически не отличается от оператора IF в Visual Basic 6.0. Но одно небольшое отличие все же существует: часть выражения, следующая после ключевого слова THEN, более не нужна. Кроме этого, VB.NET является по умолчанию строго типизированным языком программирования. Это означает, что логическая часть программного кода должна быть фактически логическим выражением Boolean. Предыдущие версии Visual Basic сразу же преобразуют значения, что позволяет использовать, например, следующее выражение: IF 5 THEN
Рис. 8.1. Условный оператор IF
WindowsAppUcationi - Microsoft Visual Bask.NET [design] Forrni .«b gte Ed* WW i Project guild Debug Toosl - 4 В - 1 5 и , Debug
Forml,vb[Oesiqn] Forml.vb | •"jForml (WindowsApplicationl) _-J ||J\(Declarations) | Option Strict On is Public class Fomil
-
: \ Inherits 5ysteni.Windows.Forms.horm
^[WtmlowsTcH-rtt I» С M
t,
• >. bmte]
Private Sub Kornil_Load(ByV.il sender As System.Ob|ett, Byval e As System-Evcnt If 5 Then
«У
I
LiT
:. V "\
' • Descnpto in L Opto i n Strict dsiao l wsm I pbcti converso i ns from Integer to Booe l an.
Puc. 8.2. Запрещение неявного преобразования данных из System. In teger в Sys tern. Boolean Выражения с сокращенным циклом
•
127
VB.NET подобным свойством не обладает. Поэтому выполнение такой команды приводит к ошибке компиляции (рис. 8.2). Синтаксис оператора IF позволяет сгруппировать несколько условий проверки в одном условном операторе. Подобная операция выполняется с помощью одного из вариантов условного оператора— ELSEIF. Этот оператор может быть использован для проверки нескольких различных условий, содержащихся в одном операторе. Причем, если заданное условие истинно, происходит, как показано в листинге 8.5, выполнение различных действий.
Листинг 8.5. Вариант использования оператора ELSEIF IF IF sEmployeeType = "E" THEN Call HandleExemptEmployee(lEmployeelD) ELSEIF HasOverTiine(lEmployeelD) THEN Call ReportOverTime(lEmployeelD) ELSEIF WorkedNightShift(lEmployeelD) Call ReportNightShiftWorker(lEmployeelD) END IF С помощью операторов IF и ELSEIF осуществляется проверка различных условий. Если же в качестве условий используются разные значений одной и той же переменной, лучше воспользоваться оператором S e l e c t Case, о котором пойдет речь в следующем разделе.
Оператор Select Case Этот оператор (рис. 8.3) создан для упрощения процесса проверки различных условий в одном выражении. Он также является одним из операторов ветвления и позволяет выполнить одну из нескольких групп операторов, в зависимости от значения условия.
Рис. 8.3. Оператор Select Case 128
Глава 8. Управление порядком выполнения команд
Структура оператора S e l e c t Case не позволяет изменять выражение, которое оценивается для каждого из условий, как это происходит, например, при использовании конструкции I F . .ELSEIF. .END IF. Структура оператора S e l e c t Case приведена в листинге 8.6. Листинг8.6. Синтаксис оператора Select Case Select Case test expression Case expression list 'Исполняемые операторы Case expression list 'Исполняемые операторы Case Else 'Исполняемые операторы End Select Синтаксис оператора достаточно прост, но существуют некоторые свойства и тонкости, на которые следует обратить внимание при разработке программ. Во-первых, проверочное выражение должно иметь более двух значений; в противном случае лучше воспользоваться условным оператором IF. Использовать оператор S e l e c t Case для проверки выражения, значение которое оценивается булевой переменной (т.е. "да" или "нет"), по меньшей мере неразумно. Во-вторых, оценка каждого значения Case происходит до тех пор, пока не встретится первое из значений, удовлетворяющих условию или пока не будет выполнен оператор Case E l s e . Оператор Case E l s e выполняется, если ни одно из предыдущих условий не является истинным. Поэтому, учитывая все сказанное, постарайтесь размещать значения оператора Case в порядке уменьшения вероятности появления. Например, в качестве проверочного выражения используется объект Employee (Служащий), а значения Case представляют собой различные типы служащих какой-либо организации. В этом случае первым значением Case должен быть наиболее распространенный тип служащего, а последним — наименее распространенный. Значения, используемые в операторе S e l e c t Case, могут представлять собой простые или сложные выражения, примеры которых приведены ниже. Простое выражение: Case 5 Несколько различных значений, разделенных запятой: Case 5,10,15 Диапазон или область значений: Case 5 То 15 Относительное сравнение (вместо проверочного выражения можно использовать ключевое слово I s ) : Case Is > 10 Сложное выражение: Case 5,8, 11 То 15, IS > 30
Итерация или операторы цикла Для многократного выполнения одного или нескольких операторов предназначены циклы. В языке VB.NET для этого используются три основные конструкции: цикл For Next позволяет устанавливать число периодов цикла; цикл For Each используется для Выражения с сокращенным циклом
129
многократного выполнения группы операторов с помощью перечисляемых типов данных; цикл Do Loop завершается при выполнении заданного условия.
Цикл For Next В некоторых случаях необходимо выполнить один или несколько операторов определенное число раз. Наиболее эффективный метод решения этой задачи — использование оператора цикла For Next (рис. 8.4).
False
Процесс обработки
True
Рис. 8.4. Оператор For Next
Оператор For Next содержит начальное и конечное значения, величину шага (которая, если шаг равен 1, не указывается) и счетчик (листинг 8.7). При запуске цикла счетчик устанавливается в начальное значение. При каждом проходе переменная счетчика увеличивается на 1 или на величину шага. Если она достигает конечного значения, то цикл завершается и происходит выполнение следующих операторов. ЛИСТИНГ 8.7. Синтаксис оператора For Next
FOR переменная = выражение ТО выражение STEP выражение Исполняемые опера торы NEXT
Синтаксис оператора For Next достаточно прост. Наиболее сложной частью конструкции цикла является присвоение начального и конечного-значений. Синтаксис оператора включает начальное и конечное значения переменной счетчика, а также величину шага. В приведенных ниже примерах оператора For Next иллюстрируются различные способы задания начального и конечного значений и величины шага. (Обратите внимание, что в последнем примере значение шага является отрицательной величиной.) 130
Глава 8. Управление порядком выполнения команд
For I = 5 to 10 For I = 5 to 10 Step 2 For I = 100 to 10 Step -1
Следует также обратить внимание на значение переменной, при достижении или превышении которого происходит завершение цикла For Next. Например, завершение цикла For Next во второй строке произойдет при значении I, равном 12. Для безусловного выхода из цикла For Next используется оператор E x i t For. После выхода из цикла происходит выполнение строки программного кода, следующей после ключевого слова Next. Пример описанного выхода из цикла приведен в листинге 8.8. Листинг 8.8. Безусловный выход из цикла For Next For I = 1 to 100 If sEmployeeType(I) = "Salaried" Then Exit For End If Next Call ProducePayCheck(oEmployee(I))
Оператор For Each Этот оператор (рис. 8.5) используется для многократного выполнения одного или нескольких операторов посредством перебора коллекции перечисляемых элементов.
Есть элементы
Процесс обработки
Нет элементов
Рис. 8.5. Оператор For Each
Оператор For Each, как показано в листинге 8.9, обманчиво прост. Обратите внимание, что основным в этой конструкции является не синтаксис оператора, а реализация перечисляемых элементов. Выражения с сокращенным циклом
131
Листинг 8.9. Пример оператора For Each For Each элемент In группа Исполняемые операторы Next В конструкции For Each в качестве элемента используется тип System. Ob j e c t или же какой-либо определенный объектный интерфейс, реализованный всеми элементами группы. Для безусловного выхода из цикла For Each, как и из цикла For Next, используется оператор E x i t For. После выхода из цикла происходит выполнение строки программного кода, следующей после ключевого слова Next. Параметр группа должен иметь метод GetEnumerator, который возвращает объект Enumerator. Синтаксис оператора For Each в VB.NET практически не изменился, чего нельзя сказать о некоторых деталях реализации перечисляемых объектов. Большая часть коллекций и массивов объектов .NET Framework поддерживает перечисление в структурах данных языка VB.NET. Одно из существенных отличий состоит в том, что в среде .NET Framework в операторе For Each в качестве перечисляемых единиц могут использоваться элементы массива. В листингах 8.10—8.13 иллюстрируется процесс создания структуры данных, поддерживающей перечисление элементов. Для этого используются три класса: Node, S t a c k и S t a c k Enumerator. В листинге 8.10 приведен пример кода класса Node, в котором содержится строковое значение и указатели следующих элементов в списке. ЛИСТИНГ 8.10. Класс Node 'Класс Node реализует связанный список Class Node Public Value As S t r i n g Public NextNode As Node ' Конструктор класса Node с помощью текстовой строки ' извлекает следующий элемент списка Sub New(ByVal v a l As S t r i n g , ByVal nnode As Node) MyBase.New() Value = v a l NextNode = nnode End Sub End Class
Класс Stack, код которого приведен в листинге 8.11, является классом, перечисляемым в операторе For Each. Он содержит функцию GetEnumerator, которая используется в конструкции цикла для возвращения перечислителя. Для того чтобы класс S t a c k мог быть использован в конструкции For Each, он должен, по меньшей мере, обеспечивать метод GetEnumerator. Метод GetEnumerator возвращает новый экземпляр класса StackEnumerator, при инициализации которого перечисление элементов начинается с первого элемента списка. Обратите внимание, что элементы одного и того же класса S t a c k могут быть перечислены несколькими различными операторами For Each одновременно. ЛИСТИНГ 8.11.
Класс Stack
'Класс Stack сохраняет строки с помощью связанного Class Stack
132
списка
Глава 8. Управление порядком выполнения команд
Private Top As Node = Nothing 'указатель на верхний элемент 'Добавление в список новой строки Sub Push(ByVal s As String) Top = New Node(s, Top) End Sub 'Извлечение верхней строки Function Pop() As String If Top is Nothing Then Throw New Exception("Stack Empty") End If Pop = Top.Value Top = Top.NextNode End Function 'Метод GetEnumerator возвращает экземпляр класса StackEnumerator 'Каждая коллекция должна иметь метод GetEnumerator, который 'возвращает класс, поддерживающий метод MoveNext и свойство Current Function GetEnumerator() As StackEnumerator Return New StackEnumerator(Top) End Function End Class Класс S t a c k E n u m e r a t o r , код которого приведен в листинге 8.12, используется в конструкции For Each для перечисления входящих в него элементов с помощью связного списка. Класс S t a c k E n u m e r a t o r является в некотором роде "рабочей лошадкой", которая используется оператором For Each для поиска перечисляемых элементов. Для выполнения этой задачи данный класс должен поддерживать метод MoveNext и свойство C u r r e n t . Метод MoveNext переставляет элемент, находящийся на текущей позиции, на следующую позицию в списке. Свойство C u r r e n t возвращает текущую позицию. Обратите внимание, что в конструкторе текущей позицией назначена пустая позиция, расположенная в верхней части списка. Это позволяет выполнять обработку в том случае, если связный список пуст. Листинг 8.12. Класс S t a c J t E n u m e r a t o r 'Класс StackEnumerator перечисляет элементы списка Class StackEnumerator 'Метод CurrentNode указывает на текущий перечисляемый элемент Private CurrentNode As Node 'Метод MoveNext вызывается для перебора элементов списка 'Если он возвращает False, список перебора пуст Function MoveNext() As Boolean CurrentNode = CurrentNode.NextNode Return Not IsNothing(CurrentNode) End Function 'Свойство Current возвращает текущий перечисляемый элемент Readonly Property Current() As String Get Return CurrentNode.Value End Get End Property 'Создайте экземпляр StackEnumerator для перехода наверх списка Sub New(ByVal top As Node)
Выражения с сокращенным циклом
133
'Добавьте еще один верхний элемент, поскольку метод MoveNext 'вызывается перед вызовом первого элемента 'Это необходимо для обработки пустой коллекции CurrentNode = New Node(Nothing, top) End Sub End Class В листинге 8.13 приведен код VB.NET, используемый для перечисления класса Stack. При выполнении клиентского кода происходит ввод нескольких новых элементов в список, после чего используется оператор For Each для вывода этих элементов на консоль. После этого происходит удаление отдельных элементов из списка и ввод новых элементов, а затем с помощью оператора For Each вновь выполняется вывод элементов на консоль. Листинг 8.13. Перечисление класса Stack 'Пример использования описанных классов Module Modulel Sub Main() Dim Stk As New Stack() Dim Str As String Stk.Push("time") Stk.Push("the") Stk.Push("is") Stk.Push("Now") For Each Str In Stk Console.Write(Str + " ") Next Console.WriteLine () Stk.Pop() . Stk.PopO Stk.Push("isn't") Stk.Push("Now") For Each Str In Stk Console.Write(Str + " ") Next Console.WriteLine() Console.WriteLine() Console.WriteLine("Hit <Enter> when done") Console.ReadLine() End Sub End Module
Оператор Do Loop Для определения числа проходов в операторе цикла For Next: используются числовые значения. В конструкции For Each для этих же целей используется перечислитель, т.е. объект, осуществляющий нумерацию элементов некоторого набора. В отличие от этого, в конструкциях Do While Loop и Do Loop U n t i l количество проходов определяется логическим выражением, т.е. тем или иным условием, что делает эти конструкции похожими на условный оператор IF. Логические выражения могут быть простыми и 134
Глава 8. Управление порядком выполнения команд
сложными, а также содержать несколько различных условий. На рис. 8.6 представлен оператор Do While Loop, а на рис. 8.7 —Do Loop U n t i l .
False False Процесс обработки
Процесс обработки
True
Рис. S. 6. Оператор Do While Loop
Рис. S.7. Оператор Do Loop Until
Оператор Do Loop представляет собой достаточно мощную конструкцию, используемую для управления циклом. В зависимости от расположения условия, различают два варианта цикла Do Loop. Оператор Do While Loop представляет собой цикл, управляемый в начале. В этом случае программный код, содержащийся внутри цикла, может быть выполнен от нуля до нескольких раз. Цикл Do Loop U n t i l , в свою очередь, является циклом, управляемым в конце, что гарантирует выполнение цикла хотя бы один раз. Следует обратить внимание, что обе конструкции цикла Do Loop поддерживают использование оператора E x i t Do для безусловного выхода из цикла. Синтаксис оператора Do While Loop приведен в листинге 8.14, а оператора Do Loop U n t i l —в листинге 8.15. ЛИСТИНГ 8.14.
Оператор Do While Loop
Do While условие Исполняемые операторы Loop Листинг 8.15. Оператор Do Loop Until Do Исполняемые опера торы Loop U n t i l условие Change Применение операций с сокращенным циклом в языке VB.NET оказало определенное воздействие на операторы Do Loop. В качестве примера рассмотрим оператор Do Loop, Выражения с сокращенным циклом
135
условие которого состоит из нескольких условий, содержащих логические операторы. В предыдущих версиях Visual Basic в этом случае были бы выполнены все функции условий. В VB.NET в том случае, если первое условие удовлетворяет общему условию, последующие не выполняются. Оператор цикла Do Loop, как и условный оператор IF, может, с одной стороны, значительно повысить эффективность программных разработок, но с другой — вызвать некоторые проблемы в традиционных системах. Это происходит, например, в тех случаях, когда частью условия является функция, которая должна быть выполнена.
Оператор While Loop Компания Microsoft внесла некоторые синтаксические изменения: теперь вместо оператора While Wend используется оператор While End While. Многие разработчики находят синтаксис этого оператора безобразным, но его функциональные возможности практически эквивалентны возможностям оператора Do Loop. Единственным отличием является оператор E x i t Do, используемый для безусловного выхода из цикла Do Loop. Кстати, на оператор While End While, как и на условный оператор IF или операторы Do Loop, определенное влияние оказали операции с сокращенным циклом.
Неиспользуемые операторы Visual Basic содержит множество унаследованных логических операторов. Одни из них были удалены из языка VB.NET, а другие определенным образом изменены. Стремясь упростить структуру языка, Microsoft удалила несколько языковых элементов Visual Basic, в число которых вошли также некоторые логические операторы. VB.NET, например, не поддерживает операторы GoSub, On x Goto или On x GoSub. Это связано с тем, что указанные операторы используются достаточно редко, а их использование, как правило, приводит к появлению неструктурированного кода. Разработчикам Visual Basic подобные операторы более не нужны. Обратите внимание, что операторы On E r r o r Goto и GoTo не были удалены, хотя это и следовало бы сделать.
Резюме Basic превратился из языка с несколькими конструкциями структурного программирования в строго структурированный язык программирования. Фактически VB.NET внес минимальные изменения в программные конструкции предыдущих версий, что выразилось, например, во вводе в структуру языка операций с сокращенным циклом, используемых для повышения эффективности разработок. Эта возможность основана на выполнении именно того фрагмента кода, который должен быть выполнен в данный момент. Код, при создании которого разработчик не воспользовался преимуществами операций с сокращенным циклом, должен быть переписан. В заключение следует отметить, что компания Microsoft улучшила некоторые традиционные конструкции, а также удалила те из них, которые не соответствуют существующим на сегодняшний день способам программирования. Это приводит к определенным изменениям существующего кода, но в конечном счете помогает разработчикам создавать более работоспособные системы.
136
Глава 8. Управление порядком выполнения команд
Обработка ошибок Обработка ошибок— это процесс устранения ситуаций, когда что-то происходит не так, как надо. Проблемы, с которыми придется столкнуться, могут быть сгруппированы по двум категориям: относящиеся к окружению и созданные разработчиками. К проблемам окружения могут быть отнесены, например, дискета, отсутствующая в дисководе, неработающая сеть или недоступная база данных. Эти события не могут быть предусмотрены заранее, но так или иначе с ними придется столкнуться. Зачастую проблемы, созданные разработчиком, представляют собой события, которых можно было бы избежать, приняв заранее соответствующие меры предосторожности. (Причем это предпочтительнее организации ловушек для перехвата непредвиденных ситуаций.) К примерам типичных программных ошибок можно отнести деление целого числа на нуль, обращение к элементу массива с несуществующим индексом или использование необъявленной объектной переменной. Обработка ошибок является наиболее важным аспектом создания надежных приложений. Позволить ошибке "перебраться" к пользователю — самое худшее, что может сделать разработчик. Соответствующая процедура обработки ошибок исправляет те ошибки, которые могут быть исправлены, а также регистрирует неустранимые ошибки и возвращает пользователю понятное сообщение об обнаруженных ошибках. Существует два вида обработки ошибок: исключения бизнес-правил и обработка исключительных ситуаций, связанных с проблемами компьютерных систем. Иногда вторым видом обработки ошибок пренебрегают, так как это непосредственно не связано с бизнес-требованиями. В предыдущих версиях Visual Basic наиболее распространенный метод обработки ошибок состоял в использовании оператора On Error. Следует заметить, что одновременно с этим оператором использовался целый ряд других объектов и операторов для регистрации происходящих ошибок, для обработки ошибок, вызванных при обращении к функциям API, а также для продолжения обработки данных после завершения обработки ошибок.
Существует ряд проблем, связанных с этим методом обработки ошибок. Во многих ситуациях довольно трудно определить, какой из обработчиков ошибок используется в настоящее время. Для каждого компонента существуют собственные способы обработки ошибок: методы обработки ошибок, относящихся к СОМ-компонентам; возврат кода ошибки, возникающей при обращении к API; способы обработки ошибок, появляющихся при обработке базы данных. Способы обработки ошибок в .NET Framework изменились. Обработка ошибок интегрирована в .NET Framework, что сделало ее совместимой со всеми языками. Выбранный метод, называемый структурной обработкой исключений (structured exception handling), хорошо известен и используется во многих других языках. В отличие от метода On E r r o r , он предлагает гораздо более изящное решение. В среде .NET Framework любая обработка ошибок выполняется с помощью метода структурной обработки исключений. Фактически этот метод непосредственно встроен в .NET Framework. Способ обработки ошибок с помощью оператора On E r r o r все еще поддерживается языком VB.NET. Но, несмотря на это, выполнение метода On E r r o r и соответствующих ему команд "в глубинах" VB.NET происходит с помощью метода структурной обработки исключений. Обработка исключительных ситуаций настолько продуманно встроена в CLR, что работает с любыми компонентами, языками и даже на любом компьютере, не вызывая проблем, возникавших в предыдущих версиях Visual Basic. Механизм обработки исключений более устойчив, быстр и совместим со многими языками.
Класс System.Exception Структурная обработка исключений представляет собой объектно-ориентированный подход к обработке особых ситуаций. Другими словами, информация, относящаяся к возникшей исключительной ситуации, является объектом. В среде .NET Framework все исключения унаследованы из класса System. E x c e p t i o n , поэтому необходимо знать, какая из исключительных ситуаций обеспечивает тот или иной тип информации. Свойства основного класса исключений и предоставляемая информация приведены в табл. 9.1. Таблица 9.1. Свойства класса System.Exception Свойство HelpLink
Описание Позволяет разработчику получать подробную справочную информацию в форме унифицированного указателя (URL) или унифицироЕ1анного имени (URN) информационного ресурса
i n n e r E x c e p t i o n Обеспечивает метод, позволяющий создавать вложенные исключения. Таким образом, разработчик может добавлять в исходное исключение какие-либо дополнительные исключения Message
Обеспечивает локализованное описание происшедшего исключения
StackTrace
Обеспечивает полное описание стека вызовов, включая номер строки и имя файла исходного кода
Оператор Try...Catch...Finally Одной из конструкций, используемых в VB.NET для обработки исключений, является оператор T r y . . . C a t c h . . . F i n a l l y . Он позволяет выделить часть программного кода, 138
Глава 9. Обработка ошибок
которую разработчик планирует проверять. Оператор Try. . . C a t c h . . . F i n a l l y в этом случае может быть вложенным. Когда возникает исключительная ситуация, предложение Catch перехватывает исключение и применяет одну из схем обработки особых ситуаций. (Предположим, что для данного случая существует определенная схема обработки исключений. Более подробно эта ситуация рассматривается несколько позже.) Используемое предложение F i n a l l y содержит код очистки и является гарантией его выполнения независимо от результата кода, полученного в предложениях Try и Catch. Пример использования оператора T r y . . . C a t c h . . . F i n a l l y приведен в листинге 9.1. ЛИСТИНГ9.1. Оператор Try. . . Catch. . . Finally Try
'Код, служащий причиной исключительной ситуации Catch oException as SomeSortOfException When OptionalExpression 'Код, выполняемый при возникновении исключительной ситуации Finally 'Код, выполняющийся всегда End Try
Предложение Try Это предложение содержит фрагмент кода, который может послужить причиной исключительной ситуации. Код, находящийся в предложении Try, выполняется до возникновения исключения или до завершения кода. Как только возникает исключительная ситуация, CLR сразу же начинает поиск первого предложения C a t c h , которое обрабатывает это исключение или исключение, являющееся частью иерархии наследования. Все исключения являются объектами, которые в конечном счете непосредственно наследуются из класса S y s t e m . E x c e p t i o n . В предложениях Catch, создаваемых при разработке обработчика ошибок, можно использовать как явные типы исключений, так и более обобщенные. Когда возникает исключительная ситуация, первое предложение C a t c h определяет тип исключения, после чего выполняет его обработку. Все это достаточно важно: пример, который будет приведен несколько ниже, позволит понять суть описанного.
Оператор Exit Try Этот оператор используется для безусловного выхода из блока Try. Он практически не отличается от операторов E x i t For и E x i t Do, которые выполняют те же функции соответственно в циклах For и Do.
Предложение Catch Предложение Catch состоит из двух частей, одна из которых обязательна. Описание исключения (exception declaration) представляет собой объектный параметр, тип которого в конечном счете должен быть наследован из класса System. E x c e p t i o n . Дополнительное предложение When позволяет выполнить дальнейшую фильтрацию для поиска фактической причины возникшего исключения. В операторе T r y . . . C a t c h . . . F i n a l l y должно быть по крайней мере одно или несколько предложений Catch. Если предложение Catch, соответствующее данному исключению, отсутствует, выполняется предложение F i n a l l y , а исключение, в свою очередь, передается по цепочке вызовов. Оператор Try..-Catch...Finally
139
Перехват исключений в предложениях Catch должен выполняться, начиная с наиболее общих и заканчивая наименее определенными исключениями. Обычно выполняется только первое предложение Catch, соответствующее тому или иному исключению. Если вы неосторожно разместили более общее предложение Catch перед более специфическим, то последнее не выполнится никогда.
ПредложениеFinally Предложение F i n a l l y содержит фрагмент программного кода, который должен быть выполнен независимо от того, является ли код предложения Try исключением или нет. Это свойство имеет особое значение для таких ресурсов, как файлы и соединения базы данных, которые должны быть закрыты независимо от способа выхода из работающей программы. В предыдущих версиях Visual Basic выполнить подобную операцию было гораздо сложнее.
Оператор Throw Существуют ситуации, когда код должен самостоятельно создавать исключение. Это происходит обычно в тех случаях, когда код обнаруживает недопустимое условие или предложение Catch должно разместить исключение поверх цепочки вызовов. Самостоятельно создать исключение можно с помощью оператора Throw: Throw объект-исключение Тип объекта-исключения должен быть наследован из класса Sys tern. E x c e p t i o n . В языке VB.NET для обработки исключений может быть использован также синтаксис E r r . R a i s e из предыдущих версий Visual Basic. Мы не рекомендуем применять этот метод в новых проектах, но при повторном использовании уже существующего кода он будет работать должным образом.
Реализация структурной обработки исключений Код из листинга 9.2 использует для обращения к файловой системе один из методов среды .NET Framework. Этот код открывает системный журнал и выводит его содержимое. Для обработки возможных исключений класса System. 10. lOException используется один обработчик исключений. ЛИСТИНГ 9.2. Код VB.NET, обрабатывающий исключение
Private Sub DumpFileToConsole(ByVal FileName As String) Dim oFileStream As New FileStream(FileName, FileMode.Open, FileAccess.Read) Dim oStreamReader As New StreamReader(oFileStream) Do While oStreamReader.Peek() > -1 System.Console.WriteLine(oStreamReader.ReadLine) Loop End Sub Public Sub DumpDebugLogFile() Try Call DumpFileToConsole(txtFile.Text) Catch e As lOException 140
Глава 9. Обработка ошибок
MsgBox("The File was not found") End Try End Sub Обратите внимание, что оператор T r y . . . C a t c h . . . F i n a l l y не позволяет продолжить выполнение кода с той строки, которая стала причиной исключения. (Это послужит хорошим дополнением к будущей версии VB.NET.) Кроме этого, обработка исключений класса System. 10. I O E x c e p t i o n выполняется раньше, чем обработка исключений более общего класса System. Exception. ( Определение типа исключений
V
В коде листинга 9.2 свойство Number объекта E r r (Err .Number) не используется. Это одно из преимуществ обработки исключительных ситуаций в .NET. Обработка ошибок в предыдущих версиях Visual Basic была несогласованной. Существуют специальные команды, используемые для получения ошибок, появляющихся при обращении к DLL, например E r r . L a s t D L L E r r o r . Обработка ошибок СОМ основана на H r e s u l t s (длинные необъяснимые числа). Некоторые из вызовов API-функций просто передают код ошибки в виде возвращаемого значения или параметра. В среде .NET Framework исключения являются объектами. Поэтому, если требуется создать собственные исключения, необходимо не определять или придумывать их номер, а наследовать.
Если вы опытный разработчик, то знаете, что лучше реализовать более явную обработку исключительных ситуаций. Внесенные изменения приведены в листинге 9.3. Здесь изменен оператор T r y . . . C a t c h . . . B l o c k , что позволило перехватывать исключения как System.10.FileNotFoundException, так и System.10. D i r e c t o r y N o t F o u n d E x c e p t i o n . Кроме этого, добавлено предложение Catch для перехвата исключений класса System. E x c e p t i o n и размещено на более высоком уровне в цепочке вызовов. Листинг 9.3. Оператор Г г у . . . Catch... Finally с двумя предложениями Catch Private Sub DumpFileToConsole(ByVal FileName As String) Dim oFileStream As New FileStream(FileName, FileMode.Open, FileAccess.Read) Dim oStreamReader As New StreamReader(oFileStream) Do While oStreamReader.Peek() > -1 System.Console.WriteLine(oStreamReader.ReadLine) Loop End Sub Public Sub DumpDebugLogFile() Try Call DumpFileToConsole(txtFile.Text) Catch e As FileNotFoundException MsgBox("The File was not found") Catch e As DirectoryNotFoundException MsgBox("The directory was not found") Catch e as Exception Throw e End Try End Sub
Реализация структурной обработки исключений
;
141
Размещение исключений Для размещения исключений в языке VB.NET следует воспользоваться оператором Throw. Этот оператор имеет один обязательный параметр, который является объектом, описываемым классом System. E x c e p t i o n . (В листинге 9.3 показан код, использующий исключение, размещенное в блоке Try.) Если необходимо где-либо разместить исключение, его можно сгенерировать с помощью одного из методов, представленных в листинге 9.4. Листинг 9.4. Перемещение исключений 'Создание и перемещение исключения в одном операторе Throw New System.Exception() 'Использование базового исключения 'Генерация исключения и его отдельное перемещение Dim oIOException As System.10.EndOfStreamException oIOException = new System.10.EndOfStreamException( "Sample End of Stream Exception") Throw oIOException
Гарантия выполнения очистки кода Предположим, что программа используется для создания записей в системном журнале и поэтому должна открывать файл и выполнять контрольное считывание записей. Имейте в виду, что объектное завершение в .NET Framework работает иначе, чем в предыдущих версиях Visual Basic. Например, в Visual Basic 6.0 разработчик создавал объект File, открывал его и делал запись, после чего позволял объекту выйти из области действия, закрывая файл. В языке VB.NET подобные операции могут привести к определенным проблемам, поскольку даже после того, как объект выйдет из области действия, "сборщик мусора" в течение некоторого времени не сможет его "забрать". Поэтому необходимо, чтобы файл был всегда закрыт. В листинге 9.5 используется предложение F i n a l l y , обеспечивающее обязательное закрытие файла, независимо оттого, появляется ли исключение или нет. Листинг 9.5. Оператор Try. . .Catch. . .Finally С предложением Finally, используемым для закрытия файла Private Sub DumpFileToConsole(ByVal FileName As String) Dim oFileStream As FileStream Try oFileStream = New FileStream(FileName, FileMode.Open, FileAccess.Read) Dim oStreamReader As New StreamReader(oFileStream) Do While oStreamReader.Peek() > -1 System.Console.WriteLine(oStreamReader.ReadLine) Loop Finally Try oFileStream.Close() Catch End Try End Try End Sub 142
Глава Э. Обработка ошибок
Создание пользовательских типов исключения В предыдущих версиях Visual Basic разработчик должен был описать ошибку и выдать соответствующую информацию в виде параметров данной ошибки. При решении сложных проблем приходилось создавать группы констант, содержащих информацию об ошибках. В среде .NET Framework это делать не обязательно. Существует множество типов исключений, уже определенных в среде .NET Framework. Это позволяет создавать исключения любого типа и дополнять их нужными данными. Следует заметить, что в .NET Framework также предусмотрен механизм создания собственных исключений. При создании собственного типа исключений в Visual Basic используются свойства наследования. Код, приведенный в листинге 9.6, генерирует новый тип исключения LogFileException, который наследуется из класса System. 10. IOException. Этот класс достаточно прост; здесь расширен базовый класс с помощью добавления свойства имени файла Readonly. Такое обновление повлекло за собой также изменение конструкторов. Обратите внимание, что в свойстве I n n e r E x c e p t i o n необходимо реализовывать конструктор, используемый для распространения создаваемого исключения. Листинг9.6.
Исключение
LogFileException
Public Class LogFileException I n h e r i t s System.10.IOException Private c_sFileName As String Public Sub New(ByVal message As S t r i n g , ByVal fileName As String) MyBase.New(message) c_sFileName = fileName End Sub Public Sub New(ByVal message As String, ByVal fileName As String, ByVal e As System.10.IOException) MyBase.New(message, e) c_sFileName = fileName End Sub Readonly Property FileName() As String Get Return c_sFileName End Get End Property End Class
Созданный класс исключения имеет дополнительное свойство и два новых конструктора. Один из них принимает сообщение и имя файла, а второй, кроме этого, содержит исключение типа System. 10. IOException. Пример использования созданного исключения L o g F i l e E x c e p t i o n приведен в листинге 9.7. Листинг9.7.
Использование
исключения
LogFileException
Private Sub DumpFileToConsolefByVal FileName As String) Dim oFileStream As FileStream Dim oStreamReader As StreamReader Try Try oFileStream = New FileStream(FileName, FileMode.Open, FileAccess.Read) oStreamReader = New StreamReader(oFileStream) Catch e As IOException
Реализация структурной обработки исключений
143
Throw New LogFileExceptionC'File not found", FileName, e) End Try Do While oStreamReader.Peek(). > -1 System.Console.WriteLine(oStreamReader.ReadLine) Loop Finally Try oFileStream.Close() Catch End Try End Try End Sub Кроме того, в этом приложении содержится оператор T r y . . . C a t c h . . . F i n a l l y , приведенный в листинге 9.8, который используется для перехвата исключения LogFileException. Листинг 9.8. Перехват исключения LogFileException Public Sub TryCustomeLogException() Try Call DumpFileToConsole(txtFile.Text) Catch e As LogFileException MsgBox("Encountered " & e.message & " with " & e.filename) Catch e As Exception Throw e End Try End Sub
Глобальные обработчики исключений Многие годы разработчики Visual Basic пытались найти метод, который соединил бы глобальный обработчик ошибок, активизируемый в том месте кода, где была обнаружена ошибка, без использования при этом стека. Это стало возможным в среде .NET Framework. В .NET Framework приложения выполняется в области, известной как домен приложения (application domain). Домен приложения может быть представлен в виде процесса (несмотря на то что в одном процессе может выполняться несколько доменов). Событие, выполняемое в случае появления необработанного исключения, генерируется разработчиком с помощью делегатов и событий. Пример реализации глобального обработчика с помощью класса System. AppDomain приведен в листинге 9.9. ЛИСТИНГ 9.9. Глобальный обработчик исключений в консольном приложении
Module Modulel Sub Main() AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf GlobalExceptionHandlerr Throw New ArgumentException() Console.ReadLine() End Sub Sub GlobalExceptionHandlerr(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs) Console.WriteLine("In CatchExceptions") Console.WriteLine("{0} threw a {1}", sender, e.ExceptionObject) Console.WriteLine("Leaving CatchExceptions") End Sub End Module
144
Глава 9. Обработка ошибок
Эффективное использование структурной обработки исключений Структурная обработка исключений, как и многие другие новые возможности VB.NET, потребует от разработчиков дополнительных усилий при создании проекта. ( Проектирование, проектирование и еще раз проектирование В среде .NET Framework проектирование гораздо важнее, чем даже разработка и анализ созданных приложений. Сейчас как никогда важно убедиться в том, что все сделанное верно. Среда .NET Framework предоставляет такое множество новых функциональных возможностей, что можно легко пропустить наиболее оптимальный способ выполнения той или иной задачи. Не менее легко применить какую-либо возможность неправильно, что приведет в конечном итоге к определенным проблемам. Требования к приложениям заметно возросли, поэтому роль разработчика изменилась. Большая часть времени, составляющего период разработки, затрачивается на анализ создаваемого проекта, а следовательно, все меньше времени остается непосредственно на программирование. В подобной ситуации руководство начинает сомневаться в продуктивности разработчиков, по крайне мере до тех пор, пока они не представят законченный продукт. Но напрасно. Проектирование предназначено для уменьшения фактического объема программы и одновременно с этим значительно сокращает фазу тестирования, что непосредственно связано с улучшением качества конечного продукта.
Нет ничего проще для разработчика, чем неправильное использование структурной обработки исключений. Ниже перечислены нежелательные действия. • Произвольное создание собственных типов исключения. • Добавление всего программного кода в обработчик исключений. • Замена кода условий обработчиками исключений. • Возврат всех исключений к вызывающему оператору.
Произвольное создание собственных типов исключений Когда вы приходите к мысли о создании исключения, постарайтесь в первую очередь проанализировать те из них, которые уже определены в среде .NET Framework. Убедившись в том, что это действительно нужно сделать, создайте собственные исключения, пользуясь при этом тремя принципами. • Имя создаваемого класса заказного исключения должно заканчиваться словом Exception. • Не описывайте собственный класс исключения из класса System.Exception. Выберите один из классов исключения, наиболее полно соответствующий той задаче, которую вы хотите решить. В большинстве случаев этим классом будет System.ApplicationException. • Убедитесь, что конструктор обработчика исключений позволяет создавать вложенные исключения. Структура наиболее распространенных конструкторов, применяемых в пользовательских классах исключения, приведена в листинге 9.10. Эффективное использование структурной обработки исключений
145
Листинг 9.10. Конструктор собственного исключения Public Sub New() 'Конструктор без параметров End Sub Public Sub New(ByVal Message as String) 'Конструктор с параметром End Sub Public Sub New(ByVal Message as String, ByVal Inner as Exception) 'Конструктор с InnerException End Sub
Добавление всего кода в обработчик исключений Превышение функциональных возможностей является наиболее общей ошибкой, которая может проявиться при первых попытках использования обработчика исключений. Одна из таких ошибок показана в листинге 9.11. Листинг 9.11. Запись массива объектов в базу данных Public Sub InsertEmployees(ByVal Employees() as Employee) Dim oEmployee as Employee For Each oEmployee in Employees Try Call InsertEmployeeRow(oEmployee) Catch e as Exception System.Console.WriteLine(e.Message) End Try Next End Sub Эффективность приведенного кода можно существенно повысить при реорганизации обработчика исключений, как показано в листинге 9.12. Листинг 9.12. Существенное повышение эффективности кода из листинга 9.11 Public Sub InsertEmployees(ByVal Employees() as Employee) Dim oEmployee as Employee .( Try For Each oEmployee in Employees Call InsertEmployeeRow(oEmployee) Next Catch e as Exception Systern.Console.WriteLine(e.Message) End Try End Sub Код, подобный коду из предыдущего примера, приведен в листинге 9.13. Листинг 9.13. Заключение каждой строки кода в отдельный блок Try...Catch. ..Finally Try .1=1+1 Catch e as System.Exception System.Console.WriteLine(e.Message) End Try Try If I = 5 then Try 146
Глава 9. Обработка ошибок
Call DoSomethingWhenlEqualsFive Catch e as System.Exception System.Console.WriteLine(e.message) End Try Else Try Call DoSomethingWhenlNotEqualToFive Catch e as System.Exception System.Console.WriteLine(e.Message) End Try Catch e as Exception System.Console.Writelin(e.Message) End Try Таким образом, вместо того чтобы написать программу с одним оператором Try. . .Catch. . . Finally, мы получили полную неразбериху. В листинге 9.14 приведена правильная версия кода.
Листинг 9.14. Реорганизация кода с помощью более эффективного обра ключений Try 1=1+1 If I = 5 Then Call DoSomethingWhenlEqualsFive Else Call DoSomethingWhenlNotEqualToFive End If Catch e as System.Exception System.Console.WriteLine(e.Message) End Try Как видите, структура обработчика исключений может определенным образом повлиять на объем создаваемого кода, что впоследствии повлияет на эффективность приложения в целом.
Замена кода условий обработчиками исключений Замена кода условий обработкой исключений является признаком некачественного проектирования, что приводит к увеличению объема кода и снижению его эффективности. Правильное использование обработчика исключений в VB.NET показано в листинге 9.15. Листинг 9.15. Правильное использования обработчика исключений в VB.NET Private Sub DumpFileToConsole(ByVal FileName As String) Dim oFileStream As FileStream Dim oStreamReader As StreamReader Try oFileStream = New FileStream(FileName, FileMode.Open, _ FileAccess.Read) oStreamReader = New StreamReader(oFileStream) Do While oStreamReader.Peek() > -1 System.Console.WriteLine(oStreamReader.ReadLine) Loop
Эффективное использование структурной обработки исключений
147
Finally Try oFileStream.Close() Catch End Try End Try End Sub Public Sub DumpToConsole(ByVal sFile As String) If File.Exists(sFile) Then Try Call DumpFileToConsole(sFile) Catch e As Exception Throw e End Try Else MsgBox(sFile & " does not exist.") End If End Sub Private Sub Buttonl_Click_l(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Buttonl.Click Call DumpToConsole(txtFile.Text) End Sub
Возврат всех исключений к вызывающему оператору Речь идет об обработчиках исключений, которые всего лишь возвращают исключения к строке кода, послужившей причиной их возникновения. Так поступают начинающие программисты. Обычно правильно разработанный обработчик "успевает" записывать массу данных до возврата исключении к вызывающему оператору.
Пример приложения Windows Form, использующего обработку исключений И в заключение рассмотрим небольшое приложение, используемое для просмотра текстовых файлов, код которого приведен в листинге 9.16.
Листинг 9.16. Программа просмотра журнала Imports System.10 Public Class frmLogViewer Inherits System.Windows.Forms.Form Private c_sFileName As String Private c_oFileStreain As FileStream Private c_oStream As StreamReader #Region " Windows Form Designer generated code " Public Sub New() MyBase.New() InitializeComponent() 'Добавьте любой код инициализации после вызова InitializeComponent()
148
Глав;а 9. Обработка ошибок
End Sub Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub Friend WithEvents btnSelect As System.Windows.Forms.Button Friend WithEvents btnOpen As System.Windows.Forms.Button Friend WithEvents btnView As System.Windows.Forms.Button Friend WithEvents opnDialog As System.Windows.Forms.OpenFileDialog Friend WithEvents IstLog As System.Windows.Forms.ListBox Private components As System.ComponentModel.Container 'NOTE: The following procedure is required by the Windows Form Designer 'It can be modified using the Windows Form Designer. 'Do not modify it using the code editor. <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() Me.IstLog = New System.Windows.Forms.ListBox() Me.btnSelect = New System.Windows.Forms.Button() Me.btnOpen = New System,Windows.Forms.Button() Me.btnView - New System.Windows.Forms.Button() Me.opnDialog = New System.Windows.Forms.OpenFileDialog() Me.SuspendLayout() 'IstLog Me.IstLog.Location = New System.Drawing.Point(16, 8) Me.IstLog.Name = "IstLog" Me.IstLog.Size = New System.Drawing.Size(536, 199) Me.IstLog.Tablndex = 0 'btnSelect Me.btnSelect.Location = New System.Drawing.Point(16, 216) Me.btnSelect.Name = "btnSelect" Me.btnSelect.Tablndex = 1 Me.btnSelect.Text = "Select" 'btnOpen Me.btnOpen.Location = New System.Drawing.Point(104, 216) Me.btnOpen.Name = "btnOpen" Me.btnOpen.Tablndex = 2 Me.btnOpen.Text = "Open" 'btnView Me.btnView.Location = New System.Drawing.Point(192, 216) Me.btnView.Name = "btnView" Me.btnView.Tablndex = 3
Пример приложения Windows Form, использующего обработку исключений
149
Me.btnView.Text = "View" 1
frmLogViewer
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(562, 295) Me.Controls.AddRange(New System.Windows.Forms.Control() __ {Me.btnView, Me.btnOpen, Me.btnSelect, Me.IstLog}) Me.Name = "frmLogViewer" Me.Text = "frmLogViewer" Me.ResumeLayout(False) End Sub #End Region Private Sub btnSelect_Click (ByVal sender As Systeir..Object, _ ByVal e As System.EventArgs) Handles btnSelect.Click Try opnDialog.ShowDialog() c_sFileName = opnDialog.FileName Catch exp As Exception lstLog.Items.Clear() lstLog.Items.Add(exp.Message) End Try End Sub Private Sub btnOpen_Click( ByVal sender As Object, ByVal e As System.EventArgs) Handles btnOpen.Click Try c_oFileStream = New FileStream(c_sFileName, FileMode.Open, FileAccess.Read) c_oStream - New StreamReader(c_oFileStream) Catch exp As Exception lstLog.Items.Clear() lstLog.Items.Add("You must select a file before opening") End Try End Sub Private Sub btnView_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnView.Click Dim sLog() As String Dim i As Integer Try lstLog.Items.Glear() Do While c_oStream.Peek() > -1 ReDim Preserve sLog(i) sLog(i) = c_oStream.ReadLine i = i + 1 Loop JstLog.DataSource = sLog Catch exp As Exception MsgBox(exp.Message) lstLog.Items.Add("You must select and open the file first") End Try End Sub End Class 150
ГлаЕ.а 9. Обработка ошибок
Резюме Обработка исключительных ситуаций в .NET Framework и VB.NET вышла на качественно новый уровень, что в первую очередь почувствовали разработчики Visual Basic. Более разумный подход к обработке исключений и более развитая структура объектно-ориентированных методов приведут в результате к появлению более надежных приложений. В течение короткого времени существующий код Visual Basic может быть перемещен в среду .NET Framework, которая поддерживает синтаксис обработки ошибок, используемый в предыдущих версиях языка. Обработка ошибок, как и многие другие изменения в среде .NET Framework, требует от разработчика внимательного отношения к созданию проекта. Проектирование позволяет сократить время разработки приложения, не снижая его функциональности. Это достигается за счет уменьшения времени утомительной отладки и диагностирования неисправностей, что в конечном счете сказывается на длительности цикла разработки.
Резюме
151
ГЛАВА 1 0 AD0.NET Возможность получения доступа к данным, находящимся в той или иной базе данных, является основной целью почти каждого бизнес-приложения. Объедините доступ к данным с взаимодействием бизнескомпонентов или приложений в Internet с помощью XML, и вы получите ADO.NET. "Совершенно другая модель доступа к базе данных" — именно эту фразу не раз произносили разработчики, использующие Visual Basic. Думаю, что многие читатели этой книги смогут отнести эти слова и к VB.NET. Что касается ADO.NET, то это не только еще один метод доступа к базе данных, а совершенно новая модель работы с базами данных. O T D A O K A D O . N E T
Компания Microsoft предприняла несколько попыток создания высокоуровневых API, обеспечивающих доступ к базам данных. Во время работы над Access, Microsoft разработала объектный метод взаимодействия с процессором базы данных Jet. Созданный метод доступа ныне известен как Data Access Objects, или, как его обычно называют, DAO. Прежде всего DA0 был предназначен для обеспечения доступа к базам данных Microsoft Jet, но в то же время с успехом использовался для получения доступа к источникам данных, созданных с помощью ODBC. Однако следует заметить, что производительность метода была оптимизирована все же не для ODBC, а для Access. DAO был наиболее используемым методом доступа к данным в различных версиях Access, в том числе и в Access 2000. Объектная модель DAO версии 3.6 приведена на рис. 10.1. DAO разработан для обеспечения доступа к данным при постоянном подключении к базе данных и не позволяет использовать "отключенные" данные. Этот метод предоставляет возможность применения курсоров как на стороне клиента, так и на стороне сервера. Такие курсы требуют постоянного подключения к базе данных. Описанная модель достаточно хорошо работала с приложениями Access, но во многих ситуациях возникали проблемы при работе с SQL Server и базами данных Oracle.
Для повышения эффективности работы с серверными базами данных Microsoft создала "оболочку" на верхнем уровне ODBC, получившую название Remote Data Objects (RDO). RDO обеспечила на основе ODBC высокоэффективный доступ к данным, которые содержатся в базах данных SQL. Созданная объектная модель подобна аналогичной модели DAO (ее размеры, правда, несколько меньше). Объектная модель RDO показана на рис. 10.2. RDO является модификацией DAO, предназначенной для SQL Server и других серверных СУБД. Следует подчеркнуть, что первоочередной целью разработки RDO было создание курсоров и возможность отключения от базы данных с последующим повторным подключением в более поздней точке для обновления данных. К сожалению, метод повторного подключения был реализован не совсем верно. Разработчик создавал, например, объект r d o R e s u l t S e t в среде MTS или СОМ+ на одном компьютере, после чего пытался использовать созданный объект в клиентском приложении. При этом генерировалось множество сетевых запросов, что существенно снижало масштабируемость приложения.
154
Глава 10. ADO.NET
OleDB и ADO Модели доступа к данным DAO и RDO созданы на основе | rdoEngine API, с помощью которого можно получить доступ к данным. rdoError Именно этот API и ограничивал возможности разработчиков Visual Basic реляционными источниками данных. Поэтому rdoEnvironment возникла необходимость разработки нового способа доступа к rdoConnection | любым данным на основе объектов СОМ. Компания Microsoft начинает создавать спецификацию rdoQuery доступа к данным, которая бы использовала механизмы СОМ и могла приспособиться к любому структурированному источrdoColumn нику данных. Результатом этого стали OleDB и ADO. ПоследrdoParameter | няя является реализацией OLE-автоматизации, разработанной поверх OleDB, и обеспечивает методы доступа к данным, котоrdoResultset рые могут быть представлены в табличном формате. rdoColumn ADO появилась на свет вместе с первой версией ASP в 1996 году и представляет собой метод доступа к базе данных, rdoTable используемый в ASP и обладающий высокой масштабируемоrdoColumn стью (конечно, при правильном использовании). При создании ADO в Microsoft не отказались полностью от DAO и RDO, rdoPreparedStatement | поэтому объектная модель ADO практически не отличается от моделей DAO и RDO. На первый взгляд объектные модели Ц - rdoColumn этих методов доступа к данным различны. Но обратите внимаLjrdoParameter | ние, что во всех моделях используется несколько одних и тех Рис. 10.2. Объектная же объектов. В табл. 10.1 сравниваются основные используемодель RDO мые объекты. Таблица 10.1. Доступ к реляционным базам данных с помощью ADO, RDO и DAO Цель
ADO
RDO
DAO
Подключение к базе данных
Connection
rdoConnection
Database
Хранимая процедура или оператор SQL
Command
rdoQuery
QueryDef
Возвращенный из базы данных набор данных
Recordset
rdoResultset
Recordset
rdoColumn
Field
Столбец базы данных
Field
Технология ADO не оптимизирована для работы с каким-либо определенным методом доступа к данным. Она может использоваться как со связанными, так и с несвязанными сценариями. Объектная модель ADO представлена на рис. 10.3. Основные преимущества ADO — это улучшенная поддержка несвязанных данных и возможность их передачи по сети. Итак, модель ADO наилучшим образом подходит для создания распределенных приложений баз данных. Эта модель также послужила основой для создания ADO.NET. ADO.NET Для среды .NET Framework требовался собственный метод доступа к данным, удовлетворяющий следующим условиям: • интеграция с XML; • несвязанная модель данных; •
В результате была создана ADO.NET. Прежде чем перейти к описанию объектной модели ADO.NET и способам ее использования, остановимся на наиболее значимых ее свойствах. Для увеличения масштабируемости в ADO.NET поддерживаются лишь курсоры типа Readonly и ForwardOnly. Использование таких курсоров позволяет наиболее быстро получить данные из реляционной базы данных. Этот способ характеризуется минимальным внешним воздействием на базу данных. Не стоит полагать, что ADO.NET в чем-то уступает другим моделям доступа к данным. Напротив, она позволяет избавиться от лишней неразберихи в методах доступа к базе данных. По мнению некоторых разработчиков, этот способ, хотя и ограничивает их выбор, но служит одним из вариантов решения проблем масштабируемости.
Объектная модель ADO.NET ADO.NET в среде .NET Framework состоит из трех пространств имен, которые описаны в табл. 10.2. Таблица 10.2. Пространства имен ADO.NET Пространство имен
Описание
S y s t e m . Data
В этом пространстве имен нет определенного поставщика данных (нет базы данных, разделенной на классы)
S y s t e m . D a t a . S Q L C l i Управляемый поставщик для SQLServer. Позволяет достичь наилучших ent характеристик производительности SQL Server, при работе которого используется протокол TDS System.Data.OleDB
Управляемый поставщик для провайдеров OleDB. Этот источник обеспечивает доступ к любому провайдеру OleDB
ADO.NET отличается от предыдущих методов доступа к данным, при создании которых пытались найти наиболее обобщенный метод. При работе с ODBC и OleDB и изменении источника данных необходимо лишь правильно подобрать провайдер OleDB или драйвер ODBC и нет никакой необходимости вносить изменения в существующий программный код. Это никоим образом не относится к ADO.NET. При разрабопсе приложения для SQL Server следует использовать пространство имен System.Data.SQLClient, если же впоследствии потребуется применение СУБД Oracle или DB2, придется заменить в созданном 156
Глава 10. ADO.NET
приложении исходное пространство имен на System. Data. OleDB. Наиболее общие классы доступа к данным находятся в пространстве имен System. Data. Кроме этого, существует два провайдера данных: первый позволяет получить доступ к любому источнику данных, а второй оптимизирован для SQL Server. Через некоторое время на рынке обязательно появятся провайдеры данных, оптимизированные для баз данных любого типа. В примерах, приведенных в этой главе, будет использоваться управляемый провайдер OleDB. Объекты, предоставляемые провайдером SQL Server, практически те же, за исключением префикса. Объектная модель ADO.NET показана на рис. 10.4. OleDBDataAdapter
Объектная модель ADO.NET несколько отличается от ранее описанных моделей, но, несмотря на это, между ними существует и много общего. Например, объекты OleDBConnection и OleDBCommand практически подобны объектам ADO C o n n e c t i o n и Command. Объектная модель ADO.NET, подобно ADO, представляет собой набор объектов, которые более взаимосвязаны, чем объекты DAO или RDO. Теперь перейдем к рассмотрению объектов данной модели.
Объект OleDBConnection Этот объект аналогичен объекту C o n n e c t i o n ADO и обеспечивает фактическое соединение с сервером базы данных. Он предоставляет все функциональные возможности, необходимые для выполнения команд. Объектная модель ADO.NET
157
Объект OleDBCommand Объект OleDBCommand, как и OleDBConnection, аналогичен одному из объектов ADO, в данном случае— Command. Объект OleDBCommand используется для создания хранимых процедур или командной строки SQL, выполняемой на сервере. Постарайтесь в тестовых сценариях пользоваться только строками SQL. Хранимые процедуры гораздо больше подходят для повышения эффективности и масштабируемости. Они содержат дополнительные параметры и методы для выполнения запросов, возвращающих наборы данных, скалярные значения или просто код возврата.
Объект OleDBDataReader Этот объект используется для получения набора данных из сервера базы данных. Объект OleDBDataReader предоставляет свойства Readonly и ForwardOnly, используемые для поиска данных: В листинге 10.1 приведен пример кода, выполняющего итерацию с помощью объекта ADO R e c o r d s e t , а в листинге 10.2 — с помощью объекта OleDBDataReader. Листинг 10.1. Выполнение итерации с помощью объекта ADO Recordset Do Until oPublishersRecordset.EOF Console.WriteLine(oPublishersRecordset.Fields 4> ("pub_name") .Value.ToString) oPublishersRecordset.MoveNext() Loop Обратите внимание, что метод Read, используемый в листинге 10.2, позиционирует указатель на следующей записи. Это позволяет избежать необходимости использовать метод MoveNext, который довольно часто упускается во время разработки. При первом обращении позиционирование на записи не выполняется. Кроме этого, обратите внимание, что метод Read возвращает одно из булевых значений, указывающих, было ли чтение записи успешным. Листинг 10.2. Выполнение итерации с помощью объекта ADO.NET OleDbDataReader Do U n t i l oPublishersDataReader.Read() Console.WriteLine(oPublishersDataReader.GetValue(0).ToString) Loop
Объект OleDbDataAdapter Этот объект впервые появился в ADO.NET и представляет собой контейнер, используемый для управления и хранения четырех объектов OleDBCommand. Объекты содержатся в четырех свойствах, описанных в табл. 10.3. Таблица
10.3.
Командные
объекты
OleDBDataAdapter
Свойства команды OleDBDataAdapter Описание SelectCommand
Используется для поиска данных в базе данных
insertCommand
Используется для ввода данных в базу данных
UpdateCommand
Используется для обновления данных в базе данных
DeleteCommand
Используется для удаления данных из базы данных
158
Глава 10. ADO.NET
Объект OleDBDataAdapter используется вместе с объектом D a t a S e t для обеспечения функциональных возможностей ADO.NET, описанных в оставшейся части этой главы. OleDBDataAdapter представляет собой объект, используемый для заполнения набора данных DataSet, а также является основой пакетного обновления базы данных.
Объект OleDbException При возникновении исключительной ситуации базы данных в ADO.NET образуется исключение типа OleDbException. В ADO, как вы знаете, информация об ошибке является элементом класса C o n n e c t i o n . Информация об исключении, полученная из базы данных, содержится в свойстве E r r o r s класса OleDbException. Это свойство возвращает класс O l e D b E r r o r C o l l e c t i o n , содержащий коллекцию объектов OleDbError.
Пакетные обновления RDO и ADO предоставляют метод для поиска данных в базе данных и последующего удаления связи с ней. Этот метод позволяет изменить данные в наборе данных, для чего следует ввести, удалить или заменить существующие записи с последующим повторным подключением набора данных к базе данных и вводом в базу данных выполненных изменений. При этом где-то в недрах RDO и ADO происходит непрерывное создание хранимых процедур, предназначенных для ввода, обновления или удаления записей. Зачастую это приводит к проблемам. Описанные функциональные возможности значительно улучшены в ADO.NET. Разработчик получил возможность выбора: воспользоваться командами, которые генерируются ADO.NET, или самостоятельно создать необходимые команды. Свойства I n s e r t Command, UpdateCoiranand и DeleteCommand позволяют создать соответствующие хранимые процедуры, необходимые для обработки данных. В результате уменьшится число ошибок и повысится эффективность, так как вам не придется постоянно создавать хранимые процедуры. Использование собственных хранимых процедур значительно повышает эффективность приложения, потому что созданные хранимые процедуры будут предварительно скомпилированы и помещены в кэш сервера.
Объект DataSet Это действительно мощный объект ADO.NET. В отличие от других объектов, существующих в ADO.NET, в имени этого объекта префикс OleDB или SQL не используется. Это связано с тем, что объект DataSet не связан с какой-либо базой данных. DataSet представляет собой хранилище данных "в памяти", заполненное данными OleDBDataAdapter, XML или программным кодом. DataSet предоставляет методы, используемые для сортировки, фильтрации и создания запросов к данным, содержащимся в DataSet. Объект DataSet более всего напоминает Recordset, но его возможности гораздо шире. Например, Recordset может содержать только одно результирующее множество, полученное из базы данных. DataSet, в свою очередь, содержит несколько объектов DataTable, причем каждый из объектов DataTable может быть получен из различных источников данных. Другими словами, DataSet может содержать несколько таблиц, причем между этими таблицами с помощью коллекции DataRe l a t i o n s C o l l e c t i o n могут быть созданы различные связи.
Объект DataTable Набор данных DataSet содержит коллекцию таблиц данных, известную как Dat a T a b l e . Объект DataTable представляет собой место хранения данных, полученных
Объектная модель ADO.NET
159
из базы данных (или другого источника) для заполнения DataSet. Объект DataSet может быть условно представлен как эквивалент объекта Recordset.
Объект DataRelation Объект DataSet содержит коллекцию объектов DataRelation, находящихся в свойстве D a t a R e l a t i o n C o l l e c t i o n . При создании связей между двумя объектами DataTable управление таблицами будет осуществляться точно так же, как и в базе данных. Например, вы создаете связь между двумя таблицами с помощью внешнего ключа, после чего пытаетесь добавить в дочернюю таблицу запись, значения внешнего ключа которой в родительской таблице не существует. Это приведет к возникновению исключительной ситуации. Кроме этого, объект DataRelation может использоваться для перемещения по записям DataTable с помощью метода DataRow. GetChildRows.
Поддержка ADO.NET в Visual Studio.NET Рассмотрим пример, в котором собраны вместе все описанные объекты. Для этого воспользуемся базой данных Northwind, которая поставляется с SQL Server 2000. На рис. 10.5 показана диаграмма отношений базы данных, в которую вошли таблицы Customers, Orders и Order D e t a i l s базы данных Northwind. i SQL Server Enterprise Manager - [Edit Diagram?£xanipte1' in., Fe li Wnidow Hep l Orders f OrderlD Customer ID EmployeelD OrderDate RequiredDate ShippedDate ShipVia Freight ShipName 5hipAddress ShipCity ShipRegion
л
;*>•
Customers s Customer ID CompanyName ContactName ContactTtie Address City Rego in PostaC l ode Country Phone Fax
j Order Details f OrderD l ProductID UntiPrc le Quantiy \ Dsicount
Puc. 10.5. Диаграмма базы данных Northwind
160
Глава 10. ADO.NET
Создайте новое приложение Windows;*пустая форма которого откроется в окне конструктора. При перетаскивании элемента OleDBDataAdapter, расположенного на панели инструментов, на форму вновь созданного приложения будет вызван мастер Data Adapter Configuration Wizard. Этапы работы мастера показаны на рис. 10.7-10.15. 1. Перетащите на форму приложения элемент OleDBDataAdapter, который находится на панели инструментов (рис. 10.6). Диалоговое окно, которое появится после перетаскивания элемента, показано на рис. 10.7. 2. Для того чтобы перейти в следующее диалоговое окно (рис. 10.8), щелкните на кнопке Next. Examplel MlcrosofI Visual Basic.NET [design] - Fonn1. He Edti Wew Proe j ct Bud li Qebug Dsta Took Window Help 1 0 \L Г^ tf% ^ ^-^ f a - ЛЗ . * | • I 'ft | j^, .^ ^j R R
»
Data [ Л 1 i l( Pon i ter f H DataSet Bb Oe lDbDataAdapter %1 Qe lDbConneco tin 'J ; OelObCommand ^ 1SgD l ataAdapter tj^ SoJCooneco tin •:or SiJ Server £i:p;orst j ^ Toob lox | i S Output | (2 i Ready Л«с. 70.6. Элемент OleDBDataAdapter на панели инструментов Visual Studio.NET
Ш ••-
t i n
л
Welcome to the Data Adapter Configuration Wizard Thsi wziard helps you specify the connection and database commands that the data adapter uses to select records and hande l changes to the database. You need to provide connection information and make decisions about how you want the database commands stored and executed Your ability to compe l te this wziard may depend on the permsiso i ns you have in the database. Click Next to continue.
Puc. 10.7. Диалоговое окно Data Adapter Configuration Wizard Поддержка ADO.NET в Visual Studio.NET
161
3. Создайте новое соединение с базой данных Northwind, выбрав ее в раскрывающемся списке, и щелкните на кнопке Next для перехода в диалоговое окно, показанное на рис. 10.9. 4. В диалоговом окне (см. рис. 10.9) можно выбрать один из трех параметров: Use SQL statements, Create new stored procedures и Use existing stored procedures. В данном примере установите переключатель Create new stored procedures и щелкните на кнопке Next. Появится диалоговое окно, показанное на рис. 10.10. 5. Для того чтобы упростить процесс создания хранимой прюцедуры, щелкните на кнопке Query Builder. Появится диалоговое окно Query Builder (рис. 10.11). 6. Выберите все столбцы в таблице Customers (каждый в отдельности) и щелкните на кнопке ОК (рис. 10.12). Data Adapter Conf iguraMon Wizard Choose Vour Data Connection The data adapter wil execute quere i s usn i g this connecto i n to o l ad and update data. Choose (torn the list of data connecto i n: currentyl n i Server Expo l rer or add a new connecto in it the one you want is not listed Which data connection should the data adapter u
Puc. 10.8. Выбор соединения с базой данных Data Adapter Configuration Wizard Choose a Query Type The dale adapter uses SQL statements « stored procedures. How should the data adapter access the database? Г Use SQL statements Specify a Select statement to load data, and the wizard win generate the Insert, Update, and Delete statements to save data changes. (• Create new stoied piocedure* Specify a Select statement, and the wizard will generate new stored procedures to select, insert, update, and delete records. С Use eKtsting stored piocedues Choose an existing stored procedure for each operation (select, insert, update and delete]
Puc. 10.9. Выберите создание новой хранимой процедуры
162
Глава 10. ADO.NET
Data Adapter Configuration Wizard Generate the stored procedures The See l ct statement wil be used to create the Select. Insert. Update, end Dee l te stored procedures. Typen i your SQL See l ct statement oi use the Query Bud li ?) to graphc i ayl desg i n the query. What data should the data adaptei load into the dataset?
Query Bud li er...
Advanced Opto i ns..
Puc. 10.10. Бланк запроса, используемый для создания хранимой процедуры
Cancel Puc. 10.11. Выберите все столбцы в таблице Customers 7. На рис. 10.12 показан созданный запрос, содержащий выбранные поля таблицы. Для того чтобы перейти в диалоговое окно, показанное на рис. 10.13, щелкните на кнопке Advanced Options. 8. Установите флажок, которая позволяет создавать хранимые процедуры вставки, обновления и удаления, снимите все остальные флажки и щелкните на кнопке ОК для возврата к диалоговому окну, показанному на рис. 10.12. В диалоговом окне, представленном на рис. 10.14, можно присвоить имена создаваемым хранимым процедурам. Для того чтобы перейти в это диалоговое окно, щелкните на кнопке Next. 9. После присвоения имен хранимым процедурам завершите работу мастера, щелкнув на кнопке Next. Появится следующее диалоговое окно (рис. 10.15). Поддержка ADO.NET в Visual Studio.NET
163
Data Adapter Configuration Wizard Generate the stored procedures
The Select statement mil be used lo create the Sekret. Insert. Update, and Delete stored procedures
Type in your SQL Select statement or use the Query Builder to graphcalry design the query What data should the data adapter load into « в dalasd? SELECT CustomerlD. CompanyName. ContactName, ConlactTitle. Address. City, Region. PostalCode. Country. Advanced Options
Query Builder .
Puc. 10.1.2. Запрос, Query Builder
возвращенный
Advanced SQL Generation Options Additional Insert, Update, and Delete statements can be generated to update the data source. P Generate Irueil, Update and Delete* Generates Insert, Update, and Delete statements based on your Select statement. Г" Useoptimixticconcunerey Modifies Update and Delete statements to detect whether the database has changed since the record was loaded Into the dataset. This helps prevent concurrency conFiicts. Г ReheshiheDataSet Adds a Select statement after Insert and Update statements to retrieve identity column values, default values, and other values calculated by the database.
Data Adapter Configuration Wizard Create the Stored Procedures Specify how you would like the stored procedures created
What do you want Ion
в Ihe new rioted pr oceduex?
Select JGetCustomers
Insert ] InserlCustomer
Update: jUpdateCustomet
Delete. JDeleteCustomer
Do you want the wizard to create the slewed pioceduiex in Ihe database? (• Yes, create them in the database tot me. С No, I wil manually create them. You can preview the SQL tciipt uted to generate stewed procedures and optionally copy it гсиуоиг own procedures Preview SQL Script..
Puc. 10.14. Присвойте имена хранимым процедурам
164
rnaBalO.ADO.NET
Date Adapter Configuration Wizard Complete the Data Adapter Configuration Wizard You have reached the end of the Data Adapter Confg i urato i n Wziard The data adapter TJteObDataAdapter? was confg i ured suecenMyl. Delate: * Generated See l ct Statement ' Generated Mappn igs. " Generated Insert Statement. " Generated Update Statement. •" Generated Dee l te Statement.
Cancel
Nwt>
Fn i sih
Puc. 10.15. Работа мастера завершена
- Microsoft Vi:;u«ii Bdsic.NET [design] - Formi -vb [Dfsii'.u j Ere i Edit Ve i w Protect guild Eebug Data Format I_oos l VVn idow Hep l 8 р - & | Ч * В # | * г Й в | « . О . . ^ В . а ^ | > Debug
я. 11&* «J m * j
Start Page Forml.vb[Deiign] |
|
IPS
о
в з I
Bn i d grd i to DataSet with no ReWoraNpsf ::;::: Bn i d Grd i to DataSel with RdatCTnUpi [ ;
Щ OteObConnecto i nl Ц,CHeDbDataAdapter2 J £ j ,OW»DataAdapter3 f S 1 Ш Output Item(s) Saved Puc. 10.16. Форма с элементами управления
Поддержка ADO.NET в Visual Studio.NET
165
Теперь необходимо создать еще два объекта OleDBDataAdapter для таблиц O r d e r s и Order D e t a i l s . После добавьте на форму элемент DataGrid и две кнопки. Размеры и расположение элементов управления должны примерно соответствовать изображенным на рис. 10.16. Сгенерированный код приведен в листинге 10.3. Листинг 10.3. Код, используемый для создания и проверки наборов данных Private Sub BindGridToDataSetWithRelationShip() Me.Text = "Grid is Bound to a DataSet with defined relationships" Dim oDS As New DataSet() oleDbConnectiontl().Open() oleDbDataAdapterl() .Fill (oDS, "Customers") oleDbDataAdapter2().FillfoDS, "Orders") 0leDbDataAdapter3().Fill(oDS, "OrderDetails") oleDbConnectionl() .Close () oDS.Relations.Add("CustomerOrders", oDS.Tables("Customers").Columns("CustomerlD"), _ oDS.Tables("Orders").Columns("CustomerlD")) oDS.Relations.Add("OrderOrderDetails", oDS.Tables("Orders").Columns("OrderlD"), oDS.Tables("OrderDetails").Columns("OrderlD")) dataGridl().DataSource = oDS dataGridl().DataMember = "Customers" End Sub Private Sub BindGridToDataSetNoRelationShip() Me.Text = "Grid is Bound to a DataSet with no defined relationships" Dim oDS As New DataSet () oleDbConnectionl().Open() oleDbDataAdapterl().Fill(oDS, "Customers") 0leDbDataAdapter2().Fill(oDS, "Orders") oleDbDataAdapter3().Fill(oDS, "OrderDetails") oleDbConnectionl(),Close() dataGridl().DataSource = oDS dataGridl().DataMember = "Customers" End Sub Private Sub buttonl_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonl.Click Call BindGridToDataSetNoRelationShip() End Sub Private Sub button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles button2.Click Call BindGridToDataSetWithRelationShip() End Sub
Теперь остается только запустить приложение и щелкнуть на кнопке Bind Grid to DataSet with No Relationships. Созданная форма будет выглядеть, как на рис. 10.17.
166
Глава 10. ADO.NET
'„? Grid is Bound to a DatnSef with iro defined relationships CuslomerlD ALTO ANATR ANTON AHDUT BERGS BLAUS BLQNP BOI.ID BONAP BOTTM BSBEV CACTU
•
| CompanjiNa ContactName AlndtFuHK* Maria Andeis Ana Tiuiillo E Ana Truiilo Antonio More Antonio Moie Aiound the H Thomas Hard Berglunds sn Christina Bee Bbuer See D Hanna Moos Blondesddsl Fiederique Ci Bolide. Cornel Martin Gomm Bon app' Laurence Leb Bo'lom-Dollar Elizabeth Lin B's Beverage Victoria Ashw Cactus Comi Patrcra Simp
1 Address Obele Sti 57 Avda.de la С Matadeios 2 120 Hanover Berguvsvage Forslersti 57 24. place № C/Aiequi.67 12. ruedesB 23 Tsawasse Faunlleroy D Cerrrto 333 |
" "•' Region
Berlin Межо D.F. Mexico D.F. London Lulea Mannheim Stiatbourg Madrid Mar «lie T sawatten London Buenos Aires
'
'"'"^ ^
(nulj (null
—
(null (null (null| (null)
(пиЯ) (r.u«l (null)
ВС (null) [null)
4
Bird Grid № DalaSet with Relationships
Puc. 10.17. Набор DataSet без применения отношений Щелкните на кнопке Bind Grid to DataSet with Relationships. Форма примет вид, как показано на рис. 10.18. 31 Grid is Bound (о a DataSet with defined relationships
•
"- — ~ ~ CustomerD l | CompanyNa i Contact» ameContactTkle i Address в Alfred! Fuller Mara i Anders Sae l s Repres Obere Stt. 57 Berlin в ANATR в ANTON в AROUT га BERGS
ш BLAUS в BLONP
а '_ ш
BOLD I BONAP
т
BSBEV
ш BOTTM
П
Avda de la С Ana Ttujilo E Ana TruH ij o Owner Mataderos 2 Antonio More Antonio More Owner Around the HThomas Hard Sae l s Repres 120 Hanover Berguvsvage Beg iu l nds sn Christina B« Order Admn ii Blauei See D Hanna MOOT SabsRepre; Foirleisti. 57 Bo l ndesddsl Fre"derq i ue Ci Marketn i g Ma24. place № C/Araquil,67 B6ido Comd i Martin Somm Owner 12. ruedesB Bon app" Lauience Leb Owner Botom-Doa l r Elizabeth Lin Accounting M23 Tsawaese Bs' Beverage Victoria Ashw Sae l s Repres FaunlleroyCi
Bind grid to DataSet with no Relationships
MeKicoD.F. Mexico D.F. London Lulea Mannheim Strasbourg Madrid Marseille Tsawassen London
Puc. 10.18. Набор DataSet с применением отношений Приведенный пример показывает, какое влияние оказывают отношения, определенные в наборе данных, а также как по-разному могут отображаться данные в информационных элементах управления, например в сетке данных. В листинге 10.4 приведена измененная версия метода BindGridToDataSetNoRelat i o n S h i p , который позволяет связать сетку данных с таблицей O r d e r s до организации связи с таблицей Customers. ЛИСТИНГ 10.4. Измененная версия метода BindGridToDataSetNoRelationShip
Private Sub BindGridToDataSetNoRelationShip() Me.Text = "Grid is Bound to a DataSet with no defined relationships" Dim oDS As New DataSet() oleDbConnectionl{).Open() •
Поддержка ADO.NET в Visual Studio.NET
167
oleDbDataAdapterl().Fill(oDS, "Customers") oleDbDataAdapter2().Fill(oDS, "Orders") oleDbDataAdapter3().Fill(oDS, "OrderDetails") oleDbConnectionl() .Close () dataGridl().DataSource - oDS dataGridl().DataMember = "Orders" End Sub Теперь запустите приложение еще раз и щелкните на кнопке Bind Grid to DataSet with No Relationships, как показано на рис. 10.19. В появившейся сетке будет отображена таблица Orders (рис. 10.20).
: _ ; : _ _ ШШЯШ H I RequiedOste шштI S h i p V » 3 |W Cu t o m a D l j E m p o l y e d D j O t d « D s t » ET ' 5 7/4/1996 8Л/19Э6 5S/2 0p/2p0ed0D 1a»t э1 TOMSP 6 7/571996 8/16/1996 7ЛK0/1996 HANAR 4 7/8/1936 8/5Л996 7/12/1996 2 7 Л 5/1996 8/5 Л 996 V E ID 3 8/199 S1 UC PR 4 7/9 36 8/6Л996 7/11/1996 21 7/24/1996 7/16/1996 HANAR 3 7Л0Л996 2 8/8Л996 7/23/1996 CHOPS 5 7/11/1996 2 6/9Л996 7Л 5/1936 RC ISU 9 7/12/1996 3 8/12Л 996 7Л 7/1996 WELLI 3 7Л 5/1996 2 8/13/1996 7/22/1996 HL IAA 4 7/16/1996 3 7 Л 7/1996 8/14/1996 7/23/1996 ERNSH 1 8/15/1996 7/25/1996 4 7Л а/1996 CENTC
а
|
Bn i d grid lo DataSel with no Relationships
Bn i d Grid to DataSet with Relationships
Puc. 10.20. Сетка, заполненная данными таблицы Orders Измените данные в одной из ячеек столбца CustomerlD и перейдите на другую строку. Выполненное изменение сохранится. 168
Глава 10. ADO.NET
Теперь щелкните на второй кнопке и выберите таблицу Order. На рис. 10.21 показана форма с созданной связью с таблицей C u s t o m e r O r d e r s . Щелкните на связи и перейдите, как показано на рис. 10.22, в таблицу O r d e r s . После этого измените данные в одной из ячеек столбца CustomerlD и перейдите на другую строку. Измененные данные примут первоначальное значение. Этот пример иллюстрирует сохранение родительской/дочерней связи. Ш
B U S
Grid Is Bound to a DataSet with defined relationships
ZZIZ Cuso tmeD rl | CompanyNaMaria Andeis Aflreds Fute li Ж | %H i AnaTrujilloE Trujilo вA NATR Antonio More Ana Antonio More fflA N T O N the H Thomas Hard в R OUT Around Berglunds sn Christina Ber fflA B E R G S See D Harma Moos шB LAUS Blauei BlwidesddrJ Fiederique Ci ' вB L O N P BoWoComd Martin Somm _ ffl BDL D I Bon app' Leb в B ONAP Bottom-Dollar Laurence Elizabeth Lin шB O T T M B'G Beverage Victoria Ashw ш <| BSBEV
1
~ ~ T T : | ContactName ContactTitle j Address
v
— J City
~
Sales Repres
ObereStr. 57 "Berlin
Owner Owner
Avda. de la С
Mewco D.F.
[null]
Mataderos 2 120 Hanover
Mexico D.F.
(null
London Lutea
(пиЩ (null
Mannheim
Inufl M i (null (nu«|
Sales Repies Order Admhi
Berguvsvaga
Sales Repres Fasterstr. 57 Marketing Ma 24. place № C/Araqui.67 Owner 12. rue des В Owner Accounting M 23 Tsawasse Sales Repres Faunlleroy Ci
^
i f " ^ (null
Stiasbourg Madrid Marseille T sawassen London
a _]
ВС M
^
J
Bn i d Grd i to DataSet wtih Rea l to i nshp is
Bn i d grd i to DataSet with no Relationship:
Puc. 10.21. Щелкните на ссылке CustomerOrders ' • Grid is Bound to a DataSet with defined reldtitmships i Customer.: CuHomerlD: ALFHI i CompanyNome: Allredj Futterkiite ConlactName: Mara Anders jO rderlD | CustomerlD Employed D : OrderDate i RequiedDate | ShippedDate IShipVia :
• шщзщ I ] 10692 i]10702 ffl 110835 №10952 iiiioii
ALFKI ALFKI ALFKI ALFKI ALFKI ALFKI
6 4 4
1 1 3
Bind grid to DataSet with no Relationship!
S/25/1997
10/ЗЛ997 10ЛЭ/1997 1/15/1998
Э722Л997 10731Л997
11/24Л 997
3/1БЛ 998
2/12 Л 998 4/27/1999
4/9/1998
5/7 Л 938
9/2/1997 10/13/1997 10/21/1997 1/21/1998
| У I
1 2 1
3/24/1998
3 1
4Л 3/1998
1
Bind Grid to DataSet with Relationships
Puc. 10.22. Сетка, данные которой свернуты до таблицы Orders
Строгая типизация объектов DataSet Существует еще одна совершенно фантастическая возможность ADO.NET, определяемая концепцией строгого контроля типов объекта DataSet. Приведенный пример иллюстрирует эту концепцию лучше, чем любые сказанные слова. В листинге 10.5 приведен код, используемый для вывода информации из объекта DataSet на консоль. Поддержка ADO.NET в Visual Studio.NET
169
Листинг 10.5. Вывод информации из объекта DataSet на консоль Private Sub DumpDataSetToConsole() Dim oDS As New DataSet() Dim oDataRow As DataRow oleDbConnectionl().Open() oleDbDataAdapten().Fill(oDS, "Customers") oleDbConnectionl().Close() For Each oDataRow In oDS.Tables (0) .Rows Console.WriteLine(oDataRow.Item("CustomerlD").ToString & " " & oDataRow.Item("CompanyName").ToString) Next End Sub Теперь попробуем вывести на консоль те же данные, применяя объект DataSet со строгим контролем типов. В листинге 10.6 приведен код, используемый для вывода набора данных со строгим контролем типов на консоль.
Листинг 10.6. Вывод набора данных со строгим контролем типов на кон Private Sub DumpStronglyTypedDataSetToConsole() Dim oCustomers As New CustomersOrdersAndOrderDetails() Dim oCustomerRow As CustomersOrdersAndOrderDetails.CustomersRow oleDbConnectionl().Open() oleDbDataAdapterl().Fill(oCustomers, "Customers") oleDbConnectionl() .Close () For Each oCustomerRow In oCustomers.Customers.Rows Console.WriteLine(oCustomerRow.CustomerlD.ToString & " " & oCustomerRow.CompanyName) Next End Sub Примеры, приведенные в листингах 10.5 и 10.6, иллюстрируют использование набора данных со строгим контролем типов. Это значительно упрощает как создание, так и отладку кода. Ранее разработчику приходилось для точного определения имени поля повторно обращаться к схеме базы данных. Сейчас же для этого можно с успехом воспользоваться средством IntelliSense. Как вы помните, в предыдущих версиях языка все поля таблицы содержали данные типа o b j e c t . Поэтому можно было присвоить, например, полю CompanyName числовое значение, причем в этом случае перехват ошибки не выполнялся. При использовании строгой типизации перехват ошибки произойдет не только во время выполнения следующего кода, но и при его компиляции. oCustomerRow.CustomerName = 5 Наборы данных со строгим контролем типов создаются Visual Studio.Net. Для этого выберите команду Datac>Generate Dataset, как показано на рис. 10.23. Появится диалоговое окно Generate DataSet (рис. 10.24). После выбора необходимых параметров к проекту будет добавлен объект схемы XSD, содержащий в скрытом файле код Visual Basic. Скрытый файл содержит классы, наследуемые из базовых классов ADO.NET, которые используют схему XSD для создания набора данных со строгим контролем типов. Повторно выполните код, приведенный в листинге 10.3, что позволит во время разработки создать связи с помощью конструктора схемы XSD. Для открытия окна конструктора (рис. 10.23) дважды щелкните на имени XSD-файла.
Puc. 10.23. Вызов диалогового окна Generate DataSet с помощью команды Data ^Generate Dataset у Add DataAdapter tables to either a new or existing DataSet. Choose a DataSet: ("basting:
.
.
.
I
2Л
Choose which table(s) to add to the DataSet: Customers (oteDbDataAdapterl) Й Ordei Details (oteDbOat«Adaptet3) И Orders (oleObDataAdapteiZ)
W Add an instance of this Dataset to Che designer.
Help
Puc. 10.24. В этом диалоговом окне можно настраивать параметры набора данных
Поддержка ADO.NET в Visual Studio.NET
171
Example 1 Microsoft Visual Basic.Hf T [design] CuslomcrsOrdcrsA.. FJe Ш
w
Ed»
Sew
Project
guild
Debug
Schema
Tools
JMnobw
to* В * • • ! Ж ЧЙ ft I « - ™ У J i ' B> I
ИФ
• Debug
^11 5tartPage j Forrr)l.vb[DesJ!3n] CustomeriOrde_erDct_I$.Ksd* S i
S I Customers Jcustqmers] $t CustomerD l string [* E CompanyNa string EContactNam string E Contactlltle string Address string [•
I
UE OtderiD E CustomerlD E EmptayeelD | E OrderDate [_ E RequiredDat
« string int dateTime dateTime
LSSirder Detasli |<5rder Details) 5E OrderD l tat _ ?E Productro H E UntPrc i e decm i al E Quantiy short ! £ Dsicount Fo l at M I [ n DataSet"! В XML Ready
/
Puc. 10.25. Окно конструктора схем XSD
Для создания связи между таблицами перетащите элемент отношения от одной таблицы к другой. При этом появится диалоговое окно редактора связей, показанное на рис. 10.26. После компиляции проекта строго типизированный набор данных будет содержать связь, созданную с помощью конструктора.
То define a relationship (tayref), select the parent element and key, select the child element, end then select the child Field corresponding to each parent Field. Parent element:
Key: I CustomersOrdersAndOrderDetafcKey 1
~]
New..
Dataset Properties (~ Create Foreign l^ey constraint only Update rule:
Delete rule: 3
|(Defa<Jt)
Accept/Reject riie: 3
| (Default)
Cancel
* _ J
Puc. 10.26. Диалоговое окно Edit Relation
172
Глава 10. ADO.NET
После создания связей между таблицами окно конструктора схем XSD примет вид, как на рис. 10.27. Examplei MicrosoftVfeualBar.ic.NrT[dpsign] CuslomersOrdersA.. Rie Edti Ve iw Proe j ct guild Qebuq Schema Toos l Wn idow Hep l jyp » Й| • Шг Щ Ш ' ' ! Start Page ! Forml.vb[l
*' tift- ^ '"
гл
' & * E* I > Debug
ign] CustomersOrder_.derDetails.xsd
JCustomers) <$£ CustomerlD string E CompanyNa string a E ContactNam string E ContactTitte string e Address string lii
COrders) SJfr OrdeVlD " E CustomerlD f! EmployeelD I OrderDate p RequiredDat
ИЧ ' string int dateTime dateTime
4
n iItt » ^? FO d rd eo rD n ?E E P o r u c l t d em cirtal— Un P tc irie E n tnitto s EQ D sc iu oa uy flh ao t• ;'»]' Tas!- Ust
В 113 It«n(s) Saved
Л/с. 10.27. Окно конструктора схем XSD после создания связей
Резюме Организация доступа к данным в .NET Framework — существенный шаг вперед по сравнению с предыдущими версиями. Средства Visual Studio.NET позволяют создавать расширяемые и достаточно гибкие методы поиска и перемещения данных. Существует множество самых различных возможностей ADO.NET, которые не описаны в этой главе. (Не беспокойтесь, вскоре появится масса книг, посвященных ADO.NET.) Не следует использовать ADO.NET в тех ситуациях, когда необходим постоянный доступ к базам данных. В этом случае наиболее разумным решением будет применение ADO. Использование AD0.NET более приемлемо для отключенных наборов данных.
Резюме
173
Проектирование, архитектура и реализация приложений .NET Framework Существует мнение, что .NET Framework внесет некоторую сумятицу в устоявшиеся принципы Microsoft, касающиеся проектирования, архитектуры и реализации системы. В этой главе приведены примеры, которые позволят по-новому взглянуть на хорошо знакомые возможности .NET Framework. Кроме того, здесь представлена необходимая информация, которая поможет решить проблемы, относящиеся к архитектуре приложений. В заключение речь пойдет о маркетинговых решениях Microsoft, которые для разработчиков имеют второстепенное значение. На рис. 11.1 показано, какой из составляющих .NET Framework посвящена эта глава.
Безопасность В эпоху локальных и глобальных сетей модели безопасности приложений стали более сложными, чем когда-либо. Различные модели встраивались и создавались на основе самых разных платформ. Так, например, Microsoft разработала технологию ActiveX, предназначенную для программирования компонентных объектных приложений на основе модели СОМ, а уже в ActiveX был сформирован механизм безопасности, созданный на основе доверительных отношений. В свою очередь, компания Sun Microsystems на платформе языка Java создала механизм обеспечения безопасности, загружающий удаленный код на время выполнения в ограниченную среду — "песочницу".
Visual Basic
JС
C#
it C JScrp
C++
Языки сторонних разработчиков
Спецификация единого языка
nIe trnetExp ole rr С
Основные компоненты среды исполнения .NET ASP.NET
Web-службы 11 Web Forms I
Оболочка
Элементы управления
J
Базовые классы .NET Framework Сеть
) (Ввод-вывод) (
<
сЙм+ - ) (Сообщения) (
Другие
Единая среда исполнения (управление память.)
(
Сборка мусора
)
(
) ( °ВЙДГ )
Рис. 11.1. Компоненты среды .NETFramework
Механизм безопасности, реализованный в СОМ, подразумевает использование разработчиком цифровых сертификатов и доверительных отношений. Этот механизм дает возможность пользователям и администраторам контролировать доступ к определенным узлам или категориям узлов с помощью разрешений. Данная модель основывалась только на доверии к программному обеспечению, которое практически не было защищено от внешнего воздействия Так, например, пользователь мог обратиться к узлу, с которым он находился в доверительных отношениях, и установить там компонент ActiveX. В этом случае злоумышленник мог обратиться к компьютеру пользователя с другого узла через установленный компонент и нанести определенный вред. Метод обеспечения безопасности загружаемых Java-аплетов предусматривал изоляцию на время выполнения загружаемого удаленного кода в ограниченной среде, так называемой песочнице (sandbox). При этом какие-либо действия вне песочницы не разрешались. Таким образом, например, ограничивалось использование файлов или каких-либо других ресурсов. Подобный метод жестко ограничивал возможности аплетов. В среде .NET Framework компания Microsoft создала достаточно динамичную и разумную подсистему безопасности. Обычные методы безопасности, созданные на основе песочниц, превратились в систему динамической и строгой безопасности. Теперь сборка .NET Framework может предоставлять доступ к функциональным возможностям одному пользователю и в то же время запрещать другому. С точки зрения пользователя, модель безопасности .NET Framswork похожа на систему песочниц Java. Пользователь уже может не отвечать на вопросы в диалоговом окне соответствия системы безопасности коду данного поставщика. Но, а отличие от Java, приложение .NET Framework может обратиться к защищенным ресурсам, если, конечно, соответствующие политика безопасности и категории допуска были предварительно установлены. Это позволяет .NET Framework разрешать доступ к файловой системе при доверительном использовании и запрещать в незащищенной среде. 176
Глава 1 1 . Проектирование, архитектура и реализация приложений...
Идентичность кода В основу модели безопасности .NET Security положена проверка идентичности (identity) кода. Некоторая часть информации, полученная в процессе идентификации, представляет собой имя сервера публикации, узла Internet или зоны, в которой был инициирован код, а также его совместно используемое имя. Идентичность кода используется также и в других процессах, обеспечивающих безопасность в .NET Framework. После проверки идентичности кода подсистема безопасности берет на себя управление правами доступа, определяемыми данным кодом, включая доступ к системным ресурсам и дополнительному коду. Права определяют все виды доступа к указанным ресурсам, причем один и тот же код может в разных условиях соответствовать различным правам. Например, можно предоставить доступ в файловую систему с правом чтения и записи одному из элементов приложения Windows и запретить доступ такому же элементу управления, расположенному на Web-странице.
Защита доступа к коду Права предоставляются сборкам во время выполнения и могут быть присвоены системным или сетевым администратором. Защита доступа к коду (code access security) предотвращает использование кода с более высоким уровнем доступа кодом с низким уровнем доступа, что позволяет избежать потенциальной опасности несанкционированного доступа. Для корректной работы системы защиты доступа к коду требуется система управления, созданная на основе определенных политик. Применение политик позволяет пользователям и администраторам предоставлять сборкам те или иные типы разрешений в зависимости от их местоположения. Компонент .NET Runtime предоставляет заданную по умолчанию политику, которая отражает общие разрешения, предоставляемые пользователями и организациями выполняемым приложениям, расположенным, например, в Internet, в локальной сети или на локальном жестком диске. Кроме этого, определенные разрешения в пределах защиты доступа к коду присвоены системным ресурсам. К ресурсам относится файловая система, окна на экране, буфер обмена, каналы и неуправляемые API. При попытке получения доступа к ресурсу проверяется весь стек вызовов для определения того, все ли сборки в цепочке обращений обладают соответствующими правами, позволяющими обратиться к ресурсу. Если же доступа не имеет хотя бы одна из сборок, возникает исключительная ситуация.
Идентичность прав Существует еще один механизм, используемый защитой доступа к коду — идентификация вызывающего оператора (или программы). Этот механизм используется в том случае, если в подсистему безопасности входят узел Internet или зона, общедоступное имя сборки и сервер публикаций. Управление доступом к ресурсам происходит в соответствии с правами. Таким образом, доверенная сборка приложения Windows может получить доступ к файловой системе, но та же сборка может быть лишена доступа, если она выполняется из Web-страницы, созданной на узле, не имеющем достаточных прав.
Защита доступа к коду
177
Декларативная безопасность Модель безопасности .NET Framework содержит интегрированный механизм декларативной безопасности (declarative security). Это очень мощный механизм управления доступом, обеспечивающий защиту кода во время загрузки или выполнения сборки. Стратегия декларативной безопасности позволяет разработчику использовать атрибуты для пометки классов, полей или методов. Кодирование объектов включено в метаданные сборки и приводится в действие во время ее загрузки или выполнения. Это позволяет разработчику, например, ограничить вызов класса какой-либо одной сборкой из определенного сервера публикаций.
Императивная безопасность Среда .NET Framework позволяет разработчику на более низком уровне создавать запросы подсистемы безопасности с помощью так называемой императивной безопасности (imperative security). Декларативная безопасность позволяет ограничить доступ к ранее определенному каталогу файлов того или иного компьютера. В отличие от этого, императивный запрос (т.е. запрос, создающий жесткую последовательность действий) используется для проверки разрешений в целях получения доступа к файлу, не определенному во время загрузки. Императивная безопасность чаще всего используется при работе с такими ресурсами, как, например, файловая система. Это позволяет ввести ограничения доступа к ресурсам во время работы в режиме коллективного или параллельного доступа. Другими словами, перед удалением какого-либо файла система, в частности, запрашивает, имеет ли данная сборка право на удаление указанного файла в определенной точке процесса.
Ролевая безопасность В одной организации разные пользователи (а гораздо чаще группы пользователей) могут иметь различные права по отношению к выполняемым процессам. В 1997 году представлен Microsoft Transaction Server и одновременно с этим роленая концепция безопасности. Эта концепция воплотилась в стандартный шаблон проектирования схемы доступа к базам данных с использованием идентификатора пользователя и соответствующего пароля. В ролевой системе безопасности каждому пользователю назначается та или иная роль, определяющая его права и предписывающая действия, которые, в свою очередь, оказывают определенное влияние на данные и другие процессы. Система ролевой безопасности встроена в среду .NET Framework. Это позволяет разработчикам управлять какими-либо пользовательскими действиями с помощью ролей. Каждому пользователю назначается та или иная роль, в соответстиии с которой приложения могут управлять процессом, запрещать доступ к ресурсам или, напротив, разрешать доступ к определенным процессам.
Система удаленной безопасности Одна из основных проблем COM, COM+ и DCOM состояла в обеспечении безопасности за пределами пользовательского компьютера. Модель безопасности NT с трудом позволяла осуществлять передачу контекста безопасности на другие компьютеры. Удаленная стратегия .NET Framework поддерживает модель безопасности пользовательского компьютера, домена приложения и даже бизнес-единиц. В инфраструктуре удаленной безопасности используется целый ряд стандартных механизмов безопасности. В подсистему безопасности входят протоколы аутентификации на основе открытых и закрытых ключей, протоколы аутентификации "точка—точка", например SSL или IPSEC, а также криптографические алгоритмы безопасности. 178
Глава 11. Проектирование, архитектура и реализация приложений...
Криптография Подсистема безопасности содержит не только алгоритмы криптографии, но и криптографические классы, включенные в .NET Framework для использования разработчиками приложений. Криптографические классы, содержащиеся в библиотеках .NET Framework, предоставляют разработчикам широкий выбор функциональных возможностей, позволяющих разрабатывать безопасные приложения.
Сборка мусора и управление ресурсами Одним из наиболее противоречивых изменений в VB.NET является переход от детерминированного завершения к сборке мусора, как модели управления памятью и ресурсами в .NET Framework. Для большинства пользователей новая модель значительно превосходит все предыдущие. Как считают разработчики Visual Basic, по некоторым параметрам все ранее существовавшие модели значительно уступают ей, но отдельные элементы этой модели все же могут показаться слишком сложными. На рис. 11.2 представлено положение компонента сборки мусора в структуре .NET Framework. Visual Basic ic J (
C#
C
\ f Языки сторонних J \_ разработчиков
**
JScript
Спецификация единого языка
nIe trnetExp ole rr С
Основные компоненты среды исполнения .NET ASP.NET Web-службы I Web Forms
Оболочка [Windows] i F o r m s i
Элементы управления
J
Базовые классы .NET Framework
Единая среда исполнения
[(управление памятью)
(
Сборка мусора
)
(
ГстГтГв
)
( ^ л Г н и Г )1
Рис. 11.2. Местоположение компонента сборки мусора в структуре .NETFramework
Управление ресурсами на основе СОМ-технологии Управление ресурсами на основе модели СОМ происходит с помощью метода, который называется детерминированным завершением (deterministic finalization). Этот метод основан на подсчете ссылок и представляет собой механизм учета клиентов данного объекСборка мусора и управление ресурсами
179
та. По сути, класс отслеживает количество ссылок, и, как только это число приравнивается к нулю, происходит самостоятельная очистка объекта. Детерминированное завершение представляет собой код, используемый во многих языках, несмотря на то что Visual Basic всегда скрывал этот код от разработчиков. СОМреализация этого метода построена на основе интерфейса IUnknown, использующего технологию подсчета ссылок. Интерфейс IUnknown поддерживает три следующих метода: •
AddRe f — увеличивает значение счетчика ссылок на единицу;
•
R e l e a s e — уменьшает значение счетчика ссылок на единицу;
•
Q u e r y l n t e r f a c e — определяет, поддерживаются ли другие интерфейсы данным объектом (этот метод в детерминированном завершении не используется). В сущности, каждый объект поддерживает счетчик ссылок, используемый для определения момента очистки объекта. В обязанности каждого клиента входит вызов метода AddRef при создании новой ссылки и метода R e l e a s e при каждом удалении ссылки. Эта обязанность, гарантирующая, что методы AddRef и R e l e a s e всегда будут вызваны в нужное время, ложится на клиента тяжким бременем. В Visual Basic этот процесс был скрыт от разработчиков, причем настолько хорошо, что большинство из них фактически не знали о том, что происходит. Детерминированное завершение является причиной одной из наиболее частых проблем в Visual Basic — циклических ссылок. Они представляют собой достаточно распространенную объектно-ориентированную конструкцию и возникают в том случае, когда два объекта ссылаются друг на друга (таким образом, образуется замкнутый круг). В качестве примера рассмотрим рис. 11.3, на котором показана объектная модель типичного приложения учета заказов, состоящая из пяти объектов: клиент, заказы, заказ, элементы и элемент. Каждый класс реализует родительское свойство таким образом, что экземпляры данного класса могут иметь обратную связь с родительским классом (это указано стрелками на диаграмме). Когда, например, экземпляр класса миент создает экземпляр класса заказы, то передает ему ссылку на самого себя. Это является причиной обращения класса клиент к методу AddRef, который поддерживается интерфейсом IUnknown. Описанная модель полностью повторяется на протяжении всей объектной иерархии. Клиент
L
1 Заказы
Заказ
—*_
1 Элементы
1 Элемент
Рис. 11.3. Иллюстрация циклической ссылки
180
Глава 11. Проектирование, архитектура и реализация приложений.
Ожидаемое поведение в этом случае состоит в следующем: если приложение, содержащее ссылку на экземпляр класса клиент, присваивает экземпляру значение Nothing, вся иерархия объектов будет полностью уничтожена. Фактически происходит вызов метода R e l e a s e , который поддерживается интерфейсом IUnknown класса клиент, и значение счетчика ссылок уменьшается на единицу. Если в результате этого значение счетчика ссылок будет равно нулю, произойдет уничтожение экземпляра объекта клиент. В данном примере экземпляр объекта клиент создает экземпляр класса заказы и передает ему ссылку на самого себя, поэтому значение счетчика ссылок будет все еще равно единице. В результате происходит "утечка памяти", так как после присвоения ссылке на класс клиент значения Nothing клиент не сможет общаться с экземпляром класса клиент. Несмотря на это, объект и его потомки не будут уничтожены. Существует несколько методов, которые позволяют решить проблему циклических ссылок. К наиболее распространенным относятся методы Cleanup (из шаблона проектирования Dispose в языке Java и среде .NET Framework) и WeakRef e r e n c e . Из этих двух методов чаще всего используется Cleanup. Основной способ применения метода Cleanup — добавление в данный объект с последующим вызовом перед выгрузкой объекта. Метод Cleanup, в свою очередь, вызывает аналогичный метод любых дочерних объектов, которые он содержит, после чего присваивает всем ссылкам данного объекта значение Nothing. При корректном выполнении эта методика работает достаточно хорошо, но, к сожалению, позволяет разработчику забыть о необходимости вызова метода Cleanup из клиентского приложения. Кроме того, если приложение передает экземпляр класса клиент кому-либо, достаточно сложно с точностью определить время вызова метода Cleanup. Другой распространенный подход — использование метода WeakRef e r e n c e в пределах дочерних классов для хранения ссылки на родительский класс. Единственная проблема заключается в том, что этот метод не поддерживается "родными" ключевыми словами и операторами Visual Basic. WeakRef e r e n c e представляет собой ссылку, позволяющую избежать вызова метода AddRef (в действительности сначала происходит вызов метода AddRef и почти сразу же — метода R e l e a s e ) . Это делается с помощью недокументированной (по крайней мере, в руководстве по Visual Basic) функции Ob j P t r , а также посредством вызова API. Это наилучший метод решения проблемы циклических ссылок; он позволяет избежать многочисленных проблем, связанных с методом Cleanup, но, правда, создает свои проблемы. Следует заметить, что это очень "хитрый" код и написать его не так-то легко. (Он выглядит обманчиво простым, но с его помощью не менее просто вызвать зависание интегрированной среды разработки.) Кроме этого, используется также недокументированная функция Visual Basic. (Фактически эта функция перешла BVB.NET.)
Инкапсуляция очистки Детерминированное завершение имеет собственные проблемы, но, несмотря на это, позволяет обеспечить инкапсуляцию очистки объекта. Большей частью очистка объекта весьма тривиальна и не требует немедленного выполнения каких-либо дополнительных действий. Но возможны ситуации, когда необходимо немедленное выполнение кода очистки при отсутствии обращений к тем или иным объектам. Это относится обычно к файлам, сокетам TCP/IP или другим ограниченным ресурсам. Модель детерминированного завершения упрощает этот процесс в Visual Basic, хотя в других языках использовать логику AddRef и R e l e a s e довольно сложно. В листинге 11.1 приведен пример простого класса, с помощью которого происходит отображение указателя мыши в форме песочных часов и возвращение к предыдущей форме указателя.
Сборка мусора и управление ресурсами
181
Листинг 11.1. Инкапсуляция очистки — класс ChourGlass Option Explicit Private m_iPointer As MousePointerConstants Private Sub Class_Initialize() m_iPointer = Screen.MousePointer If Not m_iPointer = vbHourglass Then Screen.MousePointer = vbHourglass End If End Sub Private Sub Class_Terminate() If m_iPointer <> vbHourglass Then Screen.MousePointer = m_iPointer End If End Sub Обратите внимание, что этот класс практически не содержит каких-либо методов или свойств, поэтому управление формой указателя полностью зависит только от свойств детерминированного завершения СОМ и Visual Basic. Так, например, с помощью детерминированного завершения происходит инициализация процедуры C l a s s T e r m i n a t e и возврат формы указателя к исходному состоянию.
Управление ресурсами среды .NET Framework Как вы знаете, в СОМ-технологии используется модель детерминированного завершения. В среде .NET Framework гораздо чаще используется сборка мусора — сравнительно новый метод инструментальных средств разработки Microsoft (правда, этот метод используется также Visual J++ и другими поставщиками). Модели сборки мусора зависят от программы очистки памяти от ненужных данных, которая называется сборщиком мусора. Эта программа контролирует процесс утилизации ресурсов в той области памяти, которая выделяется программе для динамически размещаемых структур данных. Описанная область памяти называется управляемой кучей. Как только сборщик мусора определяет, что ресурсов того или иного типа, например памяти, недостаточно, он начинает процесс сборки мусора. В .NET Framework в процессе сборки мусора используется метод Sweep and Compact. Суть этого метода, исходя из названия, такова: сборщик мусора проходит через все объекты, определяя те из них, которые следует уничтожить, а после их уничтожения сжимает используемую область памяти, что позволяет избежать фрагментации. Работа сборщика мусора начинается с предположения, что все объекты должны быть собраны и уничтожены. Каждое приложение содержит набор корней, определяющих местоположение объектов в управляемой куче. В том случае, если ссылок на какой-либо объект более не существует, корню данного объекта присваивается нулевое значение. Когда сборщик мусора определяет, что какой-либо объект доступен из корней, то отмечает его как объект, не подлежащий сборке. После этого выполняется просмотр объектов и содержащихся в них корней, которые указывают на использующие их объекты. Затем сборщик мусора повторно просматривает корни всех объектов в пределах иерархии, отмечая те объекты, которые не должны быть собраны. После завершения просмотра корней приложения сборщику мусора известно, какие из объектов еще используются, а какие могут быть уже собраны. Вернемся к иерархии объектов, показанной на рис. 11.3. Ссылка на класс клиент, которая содержится в приложении, доступна из корней. Когда эта ссылка выходит из области действия или ей явно присваивается значение Nothing, указателю корней присваива182
Глава 11. Проектирование, архитектура и реализация приложений...
ется значение N u l l . При последующем обращении к сборщику мусора экземпляр класса клиент в корнях не будет обнаружен, как и его дочерние элементы, т.е. полностью будет очищена целая иерархия. Таким образом, модель управления ресурсами, использующая сборку мусора, полностью устраняет проблему циклических ссылок. К сожалению, существуют конструкции, имеющие различные проблемы циклических ссылок, для решения которых требуется использование нового объекта .NET Framework, известного как WeakRef e r e n c e . Будучи достаточно хорошо документированным, объект WeakReference среды .NET Framework заметно отличается от аналогичного объекта Visual Basic. Тем не менее сборка мусора позволяет решить наиболее распространенные проблемы циклических ссылок без создания разработчиком дополнительного программного кода. Сравнение существующих способов освобождения ресурсов приведено в табл. 11.1. Таблица 11.1. Детерминированное завершение и сборка мусора Проблема
Детерминированное завершение
Сборка мусора
Предотвращенная проблема циклической ссылки
Да, с помощью сложного кода
Автоматически
Инкапсулированная очистка
Событие Class_Terminate
Немедленная очистка объектов Да WeakReference
Методы F i n a l i z e или D i s p o s e Нет, очистка происходит при нехватке ресурсов
Да, с помощью дополни- Встроена в .NET Framework тельного кода
Очистка объектов в системе сборки мусора, например такой, как .NET Framework, происходит в следующих случаях: •
если объектным ссылкам присвоено нулевое значение;
• в начале сборки мусора. Это означает, что, в отличие от системы детерминированного завершения, уничтожение объектов не происходит в каком-либо предсказуемом порядке или в ранее определенное время. Это привело к идее инкапсулированной очистки. Существует два метода очистки объектов VB.NET Framework. Если, например, нет необходимости в немедленном выполнении очистки, можно с успехом воспользоваться методом F i n a l i z e , пусть даже и за счет увеличения объема выполняемого программного кода (более подробно речь об этом шла в главе 5, "Создание и удаление объектов"). При использовании метода F i n a l i z e происходит следующее: в первую очередь, нужный объект отмечается для завершения; после определения того, что данный объект может быть собран, он вносится в список объектов, подлежащих завершению. Несколько позже, происходит непосредственное выполнение метода F i n a l i z e и указанный объект помещается в очередь объектов, подлежащих сборке. В среде .NET Framework существует еще один способ инкапсулированной очистки — метод Dispose. Он во многом напоминает метод Cleanup, относящийся к детерминированному завершению. К сожалению, метод Dispose, как и C l e a n u p , перекладывает всю ответственность за своевременный вызов метода на клиентские приложения. (Более подробно о шаблоне проектирования Dispose речь шла в главе 5, "Создание и удаление объектов".) Несмотря на это, применение метода шаблона проектирования Dispose гарантирует, что какие-либо ресурсы, используемые объектом, будут реализованы или же возвращены Сборка мусора и управление ресурсами
183
к предыдущему состоянию. В листинге 11.2 приведен пример использования этого метода при обработке объектов хорошо известного класса H o u r g l a s s . Листинг 11.2. Класс ChourGlass в версии VB.NET Public Class ChourGlass Implements System.Idisposable Private m_Pointer As Cursor = Cursor.Current() Public Sub New() MyBase.New () If Not m_Pointer.Current Is Cursors.WaitCursor Then Cursor.Current = Cursors.WaitCursor End If End Sub Public Sub Dispose() Implements System.IDisposable.Dispose If Not m_Pointer Is Cursors.WaitCursor Then Cursor.Current = m_Pointer End If End Sub End Class
f Изменения, внесенные в процесс сборки мусора В тот период, когда создавалась эта книга, проходили жаркие дебаты по поводу удаления детерминированного завершения и события Terminate в классах Visual Basic. Это обсуждалось в форумах, группах новостей, а также среди тех, кто занимается тестированием. Microsoft опубликовала документ одного из своих архитекторов, посвященный проблемам детерминированного завершения и сборки мусора и их совместное использования. В этом документе изложены идеи, позволяющие несколько смягчить остроту проблемы. Наиболее перспективным решением является создание события, обрабатываемого объектом во время его выхода из локальной области действия. К сожалению, эта идея в версии Beta 2 не реализована. Помните, что подобная конструкция используется довольно редко. Правда, при определенных обстоятельствах ее важность значительно возрастает.
Вопросы эффективности В этом разделе выделено несколько основных тем, которые дадут представление о процессе разработки масштабируемых и работоспособных приложений VB.NET. Существует ряд руководящих принципов, использование которых позволяет гарантировать приемлемую эффективность создаваемых приложений .NET Framework.
Масштабируемость и эффективность Иногда приходится сознательно жертвовать эффективностью приложения в целях повышения его масштабируемости. Например, состояние сессии хранится непосредственно в приложении ASP.NET. Но для максимального повышения его масштабируемости лучше воспользоваться SQL Server. Это существенно повысит масштабируемость приложения, но в то же время повлияет на его быстродействие. Подобный вариант более приемлем для многопользовательского режима, чем для работы с несколькими пользователями. Постарайтесь найти наиболее оптимальное компромиссное решение при разработке масштабируемых приложений. 184
Глава 11. Проектирование, архитектура и реализация приложений...
Взаимодействие Вызовы Win32 API и компонентов СОМ снижают эффективность приложения. Обратите внимание, что в СОМ+ снижения эффективности не наблюдается. Старайтесь избегать нескольких вызовов API подряд. Вместо этого следует воспользоваться функцией API, которая принимает большее число параметров.
Численные типы Постарайтесь, если это возможно, использовать не ссылочные типы, а численные, которые гораздо эффективнее.
Не злоупотребляйте методом Finalize Как видно из предыдущего раздела, метод F i n a l i z e наиболее близок к событию T e r m i n a t e в Visual Basic 6.0, но требует больших затрат, чем событие C l a s s _ T e r m i n a t e . Это связано с тем, что сборщику мусора для выполнения очистки классов, содержащих метод F i n a l i z e , необходимы два прохода. При первом проходе обнаруживается метод F i n a l i z e и содержащий его объект помещается в специальную очередь. Выполнение этого метода происходит затем отдельным потоком. При следующем выполнении сборщик мусора собирает все объекты, находящиеся в очереди. Ненужный код, который содержится в событии C l a s s _ T e r m i n a t e , не оказывает практически никакого влияния на эффективность приложения в Visual Basic 6.0. К .NET Framework это больше не относится, поэтому старайтесь избегать использования метода F i n a l i z e , конечно, кроме тех случаев, когда используются дефицитные ресурсы или необходимо сохранить состояние объекта перед его очисткой.
Избегайте метода On Error Разработчики Visual Basic привыкли к использованию метода On E r r o r для обработки ошибок. Этот метод все еще поддерживается в Visual Basic.NET, но выполняется гораздо медленнее, чем блок Try. . . C a t c h . . . F i n a l l y . Кроме того, в течение ближайшего времени будет продолжена оптимизация блока Try. . . C a t c h . . . F i n a l l y . О методе On E r r o r этого сказать нельзя.
Использование библиотеки классов .NET Framework Зачастую разработчики самостоятельно создают все алгоритмы, способы сортировки и т.д. В языке VB.NET библиотека классов .NET Framework содержит богатейший выбор самых различных классов, которые могут предоставить именно то, что необходимо. Поэтому в первую очередь обратитесь к библиотеке классов .NET Framework.
Архитектурный анализ Чтобы полностью описать архитектуру приложений Visual Basic.NET, потребуется отдельная книга. Но если вам уже приходилось разрабатывать приложения на основе компонентов, то вы, можно сказать, полностью подготовлены для создания решений в среде .NET Framework. Теория осталась прежней, отличается только ее реализация.
Архитектурный анализ
185
Windows DNA, DNA 2000 и .NET Framework Начиная с 1997 года, Microsoft рекламирует Windows DNA и W: ndows DNA 2000 как архитектуру, используемую для разработки приложений. Пользователи, которые не смогли разобраться, что же обозначает Windows DNA, пришли к выводу, что DNA умер с появлением .NET Framework. Это не верно, так как Windows DNA нельзя отнести к серверному программному обеспечению, СОМ-технологии или, например, средствам реализации. Windows DNA используется при многоуровневом проектировании приложений. Среда .NET Framework впервые представлена на суд общественности и 2001 году. Именно поэтому архитектура приложений .NET Framework могла быть названа Windows DNA 2001. Но это не так. Самым важным является разделение приложения на логические уровни и реализация на компонентной основе. • Уровень представления. Фактически это интерфейс пользователя, например HTML/DHTML в Web-приложениях ASP.NET или формы Windows. Среда .NET Framework состоит из компонентов, которые поддерживают уровень представления; в ASP.NET, например, в их число входят серверные элементы управления ASP.NET, в приложениях Windows — элементы управления Windows. • Уровень бизнес-правил. Состоит из компонентов, позволяющих контролировать хранение данных, а также правил, определяющих способы обработки данных. Эти правила касаются подтверждения достоверности данных, вычисления и управления. Компоненты этого уровня также могут быть использованы для управления интерфейсами других систем. • Уровень хранения данных. Содержит компоненты, используемые для управления доступом к данным, а также непосредственно механизм хранения данных, например SQL Server, серверы базы данных Oracle или Exchange 2000. Необходимо запомнить следующее: многоуровневый способ создания приложений вовсе не означает, что данные приложения должны быть спроектированы так же, как и многоуровневые компоненты, и что они должны использоваться на нескольких компьютерах одновременно. Напротив, многоуровневое приложение может быть полностью создано в одном проекте Visual Studio.NET и использоваться только на одном компьютере. Например, при создании Web-приложения ASP.NET, которое содержит класс Web Form, позволяющий управлять уровнем представления, классы, управляющие уровнем бизнес-правил, а также классы, используемые для хранения и извлечения информации из базы данных SQL Server, находятся на одном компьютере (и сама базы данных SQL Server находится на этом же компьютере). В дальнейшем, при увеличении числа пользователей, работающих с данным приложением, его части могут быть размещены в компонентах или перенесены на другие компьютеры, что позволит значительно повысить его масштабируемость.
Многоуровневая архитектура в .NET Framework Архитектура Windows DNA достаточно просто трансформируется в .NET Framework.
Уровень представления Это, вероятно, наиболее простой уровень по сравнению с существующими. В большинстве случаев этот уровень представляет собой HTML/DHTML, содержащий со стороны клиента фрагмент кода на языке JavaScript для контроля в;водимых пользователем данных и простой проверки достоверности, а также приложение Windows Form, запус186
Глава 11. Проектирование, архитектура и реализация приложений...
каемое в окне обозревателя. Кроме того, .NET Framework включает поддержку устройств Pocket PC, использующих .NET Compact Framework, а также беспроводных устройств, обслуживаемых Microsoft Mobile Information Server 2001.
Уровень бизнес-правил Это более сложный уровень, включающий множество различных служб, поддерживаемых базовой платформой. В реализации Windows (которая является единственной на сегодняшний день) уровень бизнес-правил содержит Web-службы, библиотеку классов, сервисы СОМ+ и системные службы (используемые для регистрации, контроля рабочих параметров и интеграция приложений). В приложениях .NET Framework могут быть использованы следующие серверы .NET Enterprise: • SQL Server 2000
Host Integration Server 2000;
• Exchange Server 2000 •
BizTalk Server 2000
Share Point Portal Server 2001; Mobile Information Server 2001;
•
Commerce Server 2000
Hailstorm WebServices.
Архитектура Windows DNA
n-уровневая архитектура
Сервис приложений Win DNA • COM* (сервисы компонентов) • MSMQ (сервисы передачи сообщений) • IIS (сервисы Web-приложений) • Сервисы безопасности • Выравнивание нагрузки • Поддержка XML
• СОМ+ (сервисы компонентов) • MSMQ (сервисы передачи сообщений) • IIS (сервисы Web-приложений) • Сервисы безопасности • Выравнивание нагрузки • Поддержка XML •Доступ к данным
Семейство продуктов windows DNA • Win NT/2000• BizTalk Server 2000 Technology Preview • Site Server 3.0 Commerce Edition • Exchange Server S.S • SQL Server 7.0 • SNA Server 4.0 •visual Studio 6.0
Серверы. NET Enterprises • BizTalk Server 2000 • Commerce Server 2000 • • Exchange 2000 Server SQL Server 2000 Host Integration Server 2000 ISA Server 2000 Application Center 2000 Mobile Information 2001 Server
Visual Studio.NET
Рис. 11.4. Эволюция Windows DNA
Кроме этого, можно воспользоваться службами, которые предоставляются другими поставщиками, а также, что особенно важно, использовать Web-службы, которые позвоАрхитектурный анализ
187
лят получить доступ к сторонним службам, находящимся в Internet. Взаимосвязь серверов .NET Enterprise и Visual Studio.NET показана на рис. 11.4.
Уровень данных Уровень данных может быть как самым сложным, так и наиболее простым в структуре приложения. Элементы управления этого уровня позволяют полушть доступ к механизму хранения данных (т.е. к реляционной базе данных). В .NET Framework уровень данных представляет собой пространство, в котором для обработки и передачи данных на другие уровни приложения используется технология ADO и ADO.NET. Передача данных чаще всего происходит в формате XML. Существует целый ряд методов, которые используются разработчиками для сбора данных и их преобразования для передачи другим службам. Уровень данных позволяет также использовать для хранения данных свойства службы СОМ + и Web-служб.
Серверы .NET Enterprise В течение 2000 года компания Microsoft выпустила множество серверных продуктов, которые впоследствии станут частями различных приложений .NET Framework. В первую очередь следует понять, где используются эти средства и какие сервисы они могут предоставить. В большинстве случаев эти серверы относятся к серверам .NET Enterprise, так как они работают со стандартными промышленными протоколами, такими, как HTML, XML, LDAP. SQL Server 2 0 0 0 Наверное, наиболее простым для понимания сервером является SQL Server 2000. Он предоставляет ядро реляционной базы данных и в большинстве случаев является первым используемым .NET-сервером. SQL Server 2000 глубоко интегрирован с языком XML, что связано с возможностью возвращения и обновления данных в формате XML. Exchange Server 2 0 0 0 Обеспечивает передачу сообщений различным приложениям. Этот сервер, как и SQL Server 2000, интегрирован с XML и HTTP, что позволяет выполнять обслуживание .NETприложений. BizTalk Server 2 0 0 0 Предоставляет средства для интеграции бизнес-процессов, обмена XML-документами между подразделениями компании или торговыми партнерами и объединяет их с существующими приложениями. BizTalk поставляет службы, используемые для преобразования входящих данных XML (и не только XML) во внутренний формат обработки данных и обратного преобразования внутренних форматов во внешние форматы для подразделений компании и торговых партнеров. Кроме этого, BizTalk предоставляет инструментальные средства, необходимые для настройки параметров и управления процессом обмена данными между партнерами. BizTalk содержит ряд интерфейсов и компонентов СОМ, которые могут использоваться разработчиками .NET, а также методы получения информации с помощью Web-служб и HTTP. Commerce
Server 2 0 0 0
Предоставляет средства, необходимые для разработки, использования и управления коммерческими приложениями, предназначенными для локальных сетей и Internet. Commerce Server 2000 содержит ряд компонентов и интерфейсов, используемых для анализа узлов. 188
Глава 11. Проектирование, архитектура и реализация приложений...
Host Integration Server 2 0 0 0 Предоставляет механизмы для связи с системами AS/400 и MVS. Один из механизмов, COM/Tmnsaction Integrator (СОМТГ), позволяет разработчикам объявлять программы CICS как компоненты СОМ+. Mobile Information Server 2 0 0 1 Является совершенно новым программным продуктом, позволяющим объединить мобильные устройства, такие, как портативные карманные устройства или сотовые телефоны. Sharepoint Portal Server 2 0 0 1 Представляет собой еще один новый программный продукт, который вскоре будет реализован. Целью создания Sharepoint Portal Server 2001 является упрощение процесса получения информации из различных источников и ее объединения в порталы. Sharepoint Portal Server 2001 содержит средства, необходимые для управления документами, совместным обсуждением и другими механизмами. Application Center 2 0 0 0 При планировании приложений, которые, как ожидается, впоследствии будут организованы в сценарии Web Farm (т.е. в многокомпьютерную систему), стоит хорошенько присмотреться к Application Center 2000. Это инструмент, который может быть использован для управления, создания, администрирования и решения возможных проблем многосерверных приложений. Кроме того, Application Center 2000 предоставляет средства выравнивания компонентной и сетевой нагрузки. Для добавления к Webферме нового сервера достаточно установить Windows 2000 Advanced Server и Application Center 2000. Все необходимые действия по добавлению нового сервера возьмет на себя Application Center 2000. При этом параметры программного обеспечения и конфигурации добавленного сервера будут соответствовать параметрам остальных компьютеров данного кластера. Internet Security a n d Accelerator Server 2 0 0 0 Это сервер-брандмауэр, который в среде .NET Framework используется для кэширования статического содержания, что позволяет уменьшить загрузку Web-серверов. Hailstorm
WebServices
18 марта 2001 года Microsoft представила первый набор Web-служб, предназначенный непосредственно для разработчиков. Сервисы, вошедшие в первый набор, обеспечивают интеграцию паспорта аутентификации и персонализации Microsoft, XMLмодифицированного механизма мгновенной передачи сообщений, а также службы управления календарными событиями и получением сообщений. Это позволяет объединить узлы с пользовательским календарем и отправлять сообщения по электронной почте. Паспорт интеграция встроен в Windows XP, поэтому пользователь, входя в систему, автоматически получает доступ к паспорту. В результате какой-либо узел, к которому обращается пользователь, получает все данные, относящиеся к этому пользователю (конечно, только те данные, которые были предназначены для совместного использования). Архитектурный анализ
189
Интеграция XML На первых этапах разработки .NET Framework компания Microsoft не только реализовала поддержку XML, но и сделала его ключевой частью архитектуры. В среде .NET Framework существуют следующие способы поддержки XML: •
обмен данными между объектами;
•
объектное преобразование;
•
администрирование приложений;
•
глобализация;
•
документирование;
•
Web-службы;
•
доступ к данным.
Основой технологии XML в .NET Framework является SOAP. SOAP Одной из целей проекта .NET Framework явилось интегрирование кроссплатформен ного метода с удаленным вызовом процедуры. В результате появился протокол простого доступа к объектам (Simple Object Access Protocol — SOAP). SOAP увидел свет в сентябре 1999 года, когда Microsoft впервые представила миру Visual Studio.NET. Осенью того же года на рассмотрение W3C был представлен SOAP версии 1.0. В течение следующей зимы IBM и Lotus объединились с Microsoft и оказали помощь создателю SOAP версии 1.1, которая также была представлена на рассмотрение W3C. В течение 2000 года Microsoft создала предварительную версию протокола в виде Visual Studio 6 SOAP Toolkit, несколько выпусков которой было реализовано IBM для Web-сервера Apache и языка Java. Летом 2000 года компания Sun формально заявила о поддержке SOAP. Протокол простого доступа к объектам (SOAP) первоначально разрабатывался как метод использования XML и HTTP, позволяющий выполнить удаленный вызов процедуры (Remote Procedure Calls— RPC). Несмотря на это, SOAP совместными усилиями был введен в общее употребление для поддержки и других методов вызова. SOAP обманчиво прост. В его основе лежит передача XML-сообщений.
Web-службы Web-службы позволяют внешним клиентам просматривать данные или вызывать предоставляемые функции. В качестве наиболее распространенного примера можно привести узел электронной оптовой торговли, призванный предоставить всю необходимую информации о поставке товаров. Наиболее известный способ получения подобной информации — обращение на узлы экспедиторских компаний для отслеживания номеров партии товара. Если экспедиторская компания создает Web-службу для предоставления пользователю этой информации, то при обращении к узлу электронной торговли необходимые данные отобразятся непосредственно на странице заказов. Прелесть этой модели в том, что она совершенно не зависит от типа процесса, происходящего по другую сторону Web-службы. Единственное, что потребуется при использовании протокола SOAP, — это слушатель SOAP (он прослушивает входящие запросы SOAP, созданные на основе транспортных протоколов (например, HTTP), и направляет запрос к соответствующему компоненту), который обрабатывает запросы Web-службы. 190
Глава 11. Проектирование, архитектура и реализация приложений...
"За спиной" слушателя может выполняться процесс произвольного типа, запущенный на любой платформе. Одним из требований успешного принятия SOAP был стандартный способ описания Web-службы, объявленной для внешнего использования. 25 сентября 2000 года компаниями IBM и Microsoft была представлена на рассмотрение W3C спецификация языка описания Web-служб (Web Services Description Language— WSDL) версии 1.0. Для взаимодействия с внешними источниками используется XML. (Для разработчиков, хорошо знакомых с COM, WSDL занимает то же место, что и Type Lib в XML.) Кроме того, компании Microsoft, IBM и Ariba не так давно обнародовали проект универсального описания, обнаружения и интеграции (Universal Description, Discovery and Integra-
tion — UDDI). Этот проект предназначен для использования Web-служб в качестве Webхранилища, доступного в Internet. Компания Microsoft также создала первую версию технологии, названной обнаружение Web-служб (Discovery of Web Services — DISCO), которая была опубликована на конференции разработчиков в июле 2000 года. Технология DISCO позволяет обнаружить Web-узел с помощью документов WSDL. Это помогает потенциальному клиенту Web-службы выяснить, как ее использовать. Не путайте UDDI с DISCO. Технология UDDI описывает хранение, а технология DISCO представляет собой механизм обнаружения Web-службы. При создании Webслужбы на Web-сервере с .NET Framework будет автоматически создан файл DISCO. После создания Web-служба может быть опубликована в UDDI. (В составе Visual Studio.NET есть инструментальные средства, позволяющие выполнить эту операцию непосредственно в среде разработки.) Сложив все фрагменты вместе, получим следующую картину: разработчики находят хранилище UDDI, содержащее Web-службы, которое отвечает их потребностям. После того как разработчик идентифицирует URL-адрес необходимой Web-службы, он может воспользоваться средствами Visual Studio.NET (или каким-либо другим инструментом разработки, "понимающим" DISCO) для поиска по данному URL-адресу документов WSDL, определяющих способ использования Web-службы. После того как Visual Studio.NET получит соответствующий документ WSDL, Web-служба может использоваться так же, как и любой другой компонент Visual Basic .NET. ( Основные адреса URL технологий SOAP •
Спецификация Simple Object Access Protocol (SOAP) 1.1: http:// msdn.microsoft.com/xml/general/soapspec.asp. • Спецификация Web Services Description Language (WSDL) 1.0: h t t p : / / msdn.microsoft.com/xml/general/wsdl.asp. • Проект Universal Description, Discovery and Integration (UDDI): h t t p : / / www.uddi.org. • Discovery of Web Services (DISCO): http://msdn.microsoft.com/xml/general/ disco.asp.
Создание Web-службы В том случае, когда метод объявляется как Web-служба с помощью атрибута WebMethod, единая среда исполнения (Common Language Runtime— CLR) размещает информацию в виде XML. Это позволяет Web-службе возвращать объекты, преобразованные B X M L .
Архитектурный анализ
191
По умолчанию каждый фрагмент данных в объекте сохраняется как элемент XML. Как показано в листинге 11.3, для настройки преобразования в форму XML используются атрибуты класса. Это может применяться, например, для выполнения преобразования в форму, которая соответствует существующей схеме XML. Листинг 11.3. Атрибуты XML-преобразования Imports System Imports System.Xml.Serialization Public Class Employeelnfo Private c_sFirstName As String Private c_sLastName As String Private c_sEmployeeNumber As String Private c_dtStartDate As Date Public Overloads Sub New() MyBase.New() End Sub Public Overloads Sub New(ByVal FirstName As String, ByVal LastName As String, ByVal StartDate As Date) MyBase.New() c_sFirstName = FirstName c_sLastName = LastName c_dtStartDate = StartDate End Sub <XmlElement()> Public Property FirstName() As String Get Return c_sFirstName End Get Set (ByVal Value As String) c_sFirstName = Value End Set End Property <XmlElement()> Public Property LastName() As String Get Return c_sLastName End Get Set(ByVal Value As String) c_sLastName = Value End Set End Property <XmlAttribute()> Public Property StartDate() As Date Get ' •• Return c_dtStartDate End Get Set (ByVal Value As Date) c_dtStartDate = Value End Set End Property OCmllgnore()> Public Readonly Property FullNameO As String Get Return c_sFirstName & " " & c_sLastName End Get End Property End Class
192
Глава 11. Проектирование, архитектура и реализация приложений...
Взаимодействие элементов языка Способность к взаимодействию не является новым свойством Visual Basic. В качестве примера можно привести оператор D e c l a r e , который вот уже несколько лет используется разработчиками для вызова функций API Windows. Среда .NET Framework поддерживает интеграцию и способность к взаимодействию с помощью единой среды исполнения (Common Language Runtime— CLR). Поэтому существует способ взаимодействия с традиционными API Windows, компонентами COM, Microsoft Transaction Server (MTS) и сервисами СОМ+. Немало усилий затрачено на создание компонентов, которые были бы по возможности простыми и в то же время мощными. Кроме того, ровно настолько, насколько это было необходимо для упрощения использования традиционного кода, изменен синтаксис вызова функций API Windows из Visual Basic. Оператор D e c l a r e представляет собой один из способов вызова API Windows. В большинстве случаев способность технологии СОМ к взаимодействию выражается всего лишь в создании метаданных компонента СОМ. Интеграция сервера MTS и сервисов СОМ+ достигнута с помощью атрибутов и нескольких необязательных утилит.
Вызов API Windows Visual Basic пытается уберечь разработчиков от неприятностей, связанных с разработкой некоторых элементов, например ограничено использование отдельных функциональных возможностей Windows, к которым можно непосредственно обратиться из Visual Basic. К счастью, существуют способы получения доступа к подобным возможностям с помощью API Windows.
Кроме этого, разработчики могут вводить новые функциональные возможности, создавая компоненты на основе API в других языках, например С, Fortran, Pascal и т.д. Если созданные компоненты использовались дружественными типами данных, к ним можно обратиться из Visual Basic. Использование компонентов, созданных на основе API, в среде .NET Framework происходит с помощью технологии Platform Invoke (P/Invoke). В языке Visual Basic.NET технология P/Invoke, в свою очередь, реализуется с помощью хорошо знакомого оператора Declare. Обратите внимание, что в Visual Basic.NET непосредственные обращения к API Windows происходят гораздо реже, чем в предыдущих версиях языка. Это связано с тем, что Visual Basic не поддерживал каких-либо функциональных возможностей, в результате чего приходилось прибегать к API Windows. Поэтому, прежде чем применять API, постарайтесь всесторонне исследовать свойства и возможности .NET Framework. Например, одним из вызовов API Windows, наиболее распространенных в предыдущих версиях Visual Basic, является SendMessage. Этот вызов обычно использовался разработчиками Visual Basic для передачи сообщений элементам управления ActiveX, что позволяло получить доступ к функциональным возможностям, которые были неявно объявлены интерфейсом СОМ элемента управления. В среде .NET Framework самые различные элементы управления, наследуемые из класса System.Object .MarshalByRefObject. MarshalByRefComponent . C o n t r o l , имеют метод SendMessage. Таким образом, все элементы управления форм Windows наследуют метод SendMessage. Из этого следует, что нет особого смысла в применении оператора D e c l a r e для вызова API SendMessage. Несмотря на это, в примерах, иллюстрирующих применение обращений API в языке VB.NET, будет применяться вызов SendMessage. В листинге 12.1 приведен пример использования метода SendMessage элемента управления .NET Framework Li stBox для возврата длины списка. Листинг 12.1. Использование метода SendMessage для определения длины списка Private Function GetListBoKltemLength() As Integer Const LB_GETITEMLENGTH As Integer = &H18A Dim iLength As Integer iLength = ListBoxl.SendMessage(LB_GETITEMLENGTH, ListBoxl.Selectedlndex, 0) msgbox("Length of Selected Item is " & CStr(iLength)) Return iLength End Function
Оператор Declare Синтаксис оператора D e c l a r e в Visual Basic.NET практически не изменился по сравнению с предыдущими версиями Visual Basic. Правда, появились некоторые существенные различия в функциональных возможностях, связанные с использованием оператора D e c l a r e , который имеет следующий синтаксис: Declare Sub NameOfFunctionlnDLL Lib " l i b r a r y n a m e " Синтаксис оператора, используемого для вызова функции, возвращающей значение, выглядит так: Declare Function NameOfFunctionlnDLL Lib "libraryname" As ReturnValueType Выражение NameOfFunctionlnDLL определяет имя функции в DLL, а также имя, используемое для обращения к функции в данной программе. Обратите внимание, что это имя зависит от конкретных условий. Если необходимо обратиться к функции под дру194
Глава 12. Взаимодействие элементов языка
гим именем или существующее имя недопустимо в Visual Basic, воспользуйтесь необязательным ключевым словом A l i a s , как показано в следующем примере: Declare Sub FunctionNameToUselnVB Lib "libraryname" Alias "NameOfFunctionlnDll" В данном случае libraryname является именем вызываемой библиотеки. В большинстве случаев это библиотека DLL. Определение параметров оператора D e c l a r e происходит точно так же, как и параметров стандартных функций и процедур VB.NET. В листинге 12.2 приведен пример синтаксиса оператора Declare с заданными параметрами, а в листинге 12.3 — пример использования метода SendMessage. Листинг 12.2. Оператор Declare с заданными параметрами Declare Sub FunctionNameToUselnVB Lib "libraryname" Alias "NameOfFunctionlnDll" (ParameterList) ЛИСТИНГ 12.3. Пример SendMessage Declare Function SendMessage Lib "user32" Alias "SendMessageA" ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam _ As Integer, ByVal lParam As String) As Integer Существуют определенные правила передачи параметров, которым необходимо следовать. Эта книга не в состоянии охватить все правила, которые могут потребоваться при использовании данной функции. Более подробную информацию, относящуюся к использованию API Windows в VB.NET, можно найти в книге VB Programmers Guide to the Win32 API. С оператором Declare применяется несколько необязательных ключевых слов. В листинге 12.4 приведен пример использования модификаторов доступности, связанных с оператором Declare. К модификаторам доступности, которые могут быть использованы с оператором Declare, относятся P u b l i c , P r i v a t e , F r i e n d , P r o t e c t e d и P r o t e c t e d Friend. Листинг 12.4. Модификаторы доступности оператора Declare AccessibilityModifier Declare Sub FunctionNameToUselnVB Lib "libraryname" Alias "NameOfFunctionlnDll" (ParameterList) Существует также новый набор необязательных ключевых слов, который используется, как показано в листинге 12.5, для определения порядка размещения строк. Ключевое слово MarshalingBehavior может иметь одно из трех значений: Ansi, Unicode или Auto. Значение Ansi определяет, что все строки должны быть упорядочены как строки ANSI. Значение Unicode определяет, что все строки должны быть упорядочены как строки Unicode. Значение Auto, в свою очередь, передает решение о выборе среде .NET Framework. Если же параметр MarshalingBehavior не указан явно, то ему по умолчанию присваивается значение Auto. Листинг 12.5. Использование параметра MarshalingBehavior AccessibilityModifier Declare MarshalingBehavior Sub FunctionNameToUselnVB Lib "libraryname" _ Alias "NameOfFunctionlnDll" (ParameterList) Одним из наиболее существенных изменений, относящихся в VB.NET к оператору Declare, является удаление ключевого слова Any. В предыдущих версиях Visual Basic ключевое слово Any использовалось для поддержки функций API, которые принимали несколько типов данных для одного и того же параметра. В качестве примера вновь воспользуемся методом SendMessage (листинг 12.6). Вызов API Windows
195
Листинг 12.6. Метод SendMessage с ключевым словом Any в Visual Basic 6.0 Declare Function SendMessage Lib " u s e r 3 2 " A l i a s "SendMessageA" (ByVal hwnd As long, ByVal wMsg As long, ByVal wParam As long, ByVal lParam As Any) As I n t e g e r Способ, в котором применяется ключевое слово Any, нельзя отнести к рекомендуемым, так как его использование обычно приводило к блокировке контроля типов. В связи с этим Microsoft приняла решение удалить ключевое слово Any из Visual Basic.NET. В этом языке для обработки различных типов необходимо создать несколько операторов D e c l a r e (листинг 12.7). VB.NET позволяет воспользоваться новым свойством перегрузки функции, что дает возможность объявить одно и то же имя для различных сигнатур функции. Удаление слова Any повлекло за собой увеличение объема необходимой работы, но сказалось в конечном итоге на надежности создаваемых конструкций. Листинг 12.7. Объявления VB.NET без ключевого слова Any Overloads Declare Function SendMessage Lib "user32" Alias "SendMessageA" ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer Overloads Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
Управление маршалингом Ключевые слова Marshaling оператора D e c l a r e позволяют определить точный порядок перемещения строк в вызовах API. В среде .NET Framework существует более изящное решение, которое может использоваться не только для строкового, но и для других типов данных. Это делается с помощью атрибутов. Атрибуты обеспечивают декларативный метод обработки ситуаций, в которых используются большие фрагменты программного кода. Класс A t t r i b u t e , применяемый для воздействия на параметры маршалинга, представляет собой класс System. Object . A t t r i b u t e . Mar shalAsAt t r i b u t e , или более кратко — MarshalAs. Класс MarshalAs позволяет определить способ передачи каждого из параметров в список параметров, что происходит при добавлении атрибута к определению того или иного параметра. Пример, приведенный в листинге 12.8, иллюстрирует синтаксис класса MarshalAs, использующего функцию CopyFile. Обратите внимание, что атрибут MarshalAs получает конструктор при каждом использовании. В этом примере оба экземпляра класса получают параметр UnmanagedType. LPStr, который является указателем пустого массива символов ANSI. Листинг 12.8. Атрибуты, влияющие на маршалинг Declare Auto Sub CopyFile Lib "Kernel32" (ByVal <MarshalAs(UnmanagedType.LPTStr)> e x i s t i n g f i l e As String, ByVal <MarshalAs(UninanagedType.LPTStr)> newfile As String, ByVal f a i l i f e x i s t s As Boolean) Ряд параметров может быть передан конструктору MarshalAs. Параметры содержатся в перечислении System.Runtime. InteropServices.UnManagedType следующем после элементов UnManagedType. Список параметров приведен в табл. 12.1.
196
Глава 12. Взаимодействие элементов языка
Таблица 12.1. Конструкторы MarshalAs Значение конструктора
Определение
AnsiBStr
Строка ANSI, длина которой заранее определена (один байт)
As Any
Динамический тип, определяющий тип объекта во время выполнения и размещающий данный объект в соответствии с определенным типом
Bool
Четырехбайтовое логическое значение (True = I , F a l s e = 0)
BStr
Строка Unicode, длина которой заранее определена (два байта)
ByValArray
Массив фиксированной длины. Тип U n m a n a g e d F o r m a t A t t r i b u t e должен содержать число элементов массива. В том случае, если необходимо дифференцировать существующие строковые типы, U n m a n a g e d F o r m a t A t t r i b u t e может содержать (что не является обязательным) неуправляемый тип элементов
ByValTStr
Строка буфера фиксированной длины. Тип U n m a n a g e d F o r m a t A t t r i b u t e должен содержать также размер буфера в байтах. Тип символов определяется набором символов, используемых классом
CustomMarshaler Родной тип специализированного маршалера (т.е. программного кода, выполняющего операции маршалинга). Этот код должен содержать строку следующего формата: " N a t i v e t y p e name\0Custom m a r s h a l e r t y p e n a m e \ 0 O p t i o n a l c o o k i e \ 0 " и л и " ( N a t i v e t y p e GUID}\OCustom marshaler type name\0Optional cookie\0" Error
Родной тип, соответствующий типам 14 или U4 и позволяющий экспортировать параметр в виде HRESULT в экспортируемую библиотеку типов
FunctionPtr
Указатель функции
II
Однобайтовое целое число со знаком
12
Двухбайтовое целое число со знаком
14
Четырехбайтовое целое число со знаком
18
Восьмибайтовое целое число со знаком
Idispatch
Указатель COM I D i s p a t c h . Это значение применимо только к общему объекту, но не к производному классу
Interface
Указатель интерфейса COM. GUID интерфейса получен из метаданных класса
Iunknown
Указатель COM lUnknown. Это значение применимо только к общему объекту, но не к производному классу
LPArray
Массив, длина которого определяется во время выполнения действительным размером передаваемого массива. В том случае, если необходимо дифференцировать существующие строковые типы, данный массив может содержать (что не является обязательным) неуправляемый тип элементов. Когда передача типов начинается с управляемого типа элементов, а заканчивается неуправляемым, размер массива определяется динамически. При обратном маршалинге, т.е. от неуправляемого типа к управляемому, размер массива всегда принимается равным 1
LPStr
Однобайтовая строка ANSI
LPStruct
Указатель структуры С-типа. Используется для размещения управляемых форматируемых классов и численных типов
LPTStr
Независимая от платформы строка символов: ANSI для Win9x, Unicode для WinNT
LPWStr
Двухбайтовая строка Unicode
R4
Четырехбайтовое число с плавающей запятой
R8
Восьмибайтовое число с плавающей запятой
Вызов API Windows
197
Окончание табл. 12,1 Значение конструктора
Определение
Saf e A r r a y
Автоматизация OLE SafeArray. В том случае, если необходимо дифференцировать существующие строковые типы, U n m a n a g e d F o r m a t A t t r i b u t e может содержать в массиве (что не является обязательным) неуправляемый тип элементов
Struct
Структура С-типа, используемая для размещения управляемых форматируемых классов и численных типов
Syslnt
Независимое от платформы целое число со знаком: четырехбайтовое для 32-
SysUlnt
Аппаратное натуральное установленное по размеру целое число без знака
разрядной или восьмибайтовое для 64-разрядной Windows TBStr
Длина заранее определенной независимой от платформы символьной строки (ANSI для Windows 9x или Unicode для Windows NT)
U1
Однобайтовое целое число без знака
U2
Двухбайтовое целое число без знака
U4
Четырехбайтовое целое число без знака
U8
Восьмибайтовое целое число без знака
VariantBool
Двухбайтовое логическое выражение технологии OLE (True = - 1 , F a l s e = 0)
VBByRef S t r
Специфическое значение Visual Basic
Структура оператора Declare Для передачи интерфейсов API Windows в вызове API требуется определенная структура. В предыдущих версиях Visual Basic это было довольно трудной задачей, так как типы данных, доступные в Visual Basic, зачастую не соответствовали тем типам данных, которые требовались API. Положение изменилось с появлением VB.NET. Структуры не имеют тех проблем, которые возникали в прошлом из-за несоответствия типов данных. В .NET Framework существует два класса атрибутов, которые позволяют управлять способом передачи структур. Пример использования этих атрибутов приведен в листинге 12.9. •
S t r u c t L a y o u t . Этот атрибут определяет метод размещения данных структуры и содержит три варианта расположения, которые передаются конструктору. Пример использования атрибута приведен в листинге 12.9.
•
FieldOf f Set. Этот атрибут используется в том случае, когда атрибуту S t r u c t Layout присваивается значение LayOutKind. E x p l i c i t , что позволяет разработчику точно контролировать смещения в структуре данных, а также управлять расположением различных фрагментов данных. Пример использования этого атрибута приведен в листинге 12.10.
ЛИСТИНГ 12.9. Использование атрибута StructLayout
Public Structure <StructLayout(LayoutKind.Sequential)> SystemTime Public Year As Short Public Month As Short Public DayOfWeek As Short Public Day As Short Public Hour As Short 198
Глава 12. ВзаимодеРютвие элементов языка
Public Minute As Short Public Second As Short Public Miliseconds As Short End Structure
В том случае, если в структуре данных используется перечислитель LayOutKind. E x p l i c i t , следует воспользоваться атрибутом FieldOf f Set. Обратите внимание, что в примере, приведенном в листинге 12.10, применяется не только атрибут FieldOf f Set, но и типы без знака. Листинг 12.10. Использование атрибута FleldOffSet Public Class <StructLayout(LayoutKind.Explicit)> SYSTEM_INFO Private Oemld As System.UInt64 Private PageSize As System.UInt64 Private ActiveProcessorMask As System.UInt64 Private NumberOfProcessors As System.UInt64 Private ProcessorType As System.UInt64 End Class
Использование компонентов .NET Framework в СОМ-приложениях Свойство межъязыкового взаимодействия среды .NET Framework позволяет использовать компоненты .NET Framework из неуправляемого кода СОМ, включая приложения, созданные в предыдущих версиях Visual Basic, VBA, Active Server Page, других языках COM, а также языках сценариев. Как только клиент СОМ создает экземпляр .NET-компонента, в среде .NET Framework создается вызываемый упаковщик COM (COM Callable wrapper— CCW). Этот упаковщик невидим для других классов .NET Framework. Целью его создания является интеграция с неуправляемым программным кодом СОМ. Для уменьшения непроизводительных затрат каждый экземпляр компонента .NET Framework может иметь только один CCW, независимо от количества существующих внешних ссылок к данному экземпляру. Упаковщик CCW посредством интерфейсов I D i s p a t c h или IUnknown делает доступными компоненты .NET Framework для неуправляемых СОМ-клиентов. Другими словами, неуправляемый код СОМ может вызывать с помощью раннего или позднего связывания компоненты .NET Framework.
Создание "строгих" имен Компонентам .NET Framework требуются так называемые строгие имена, которые, подобно GUID, гарантируют уникальность. Эти имена создаются посредством хеширования 128-разрядного ключа и строкового имени компонента или сборки. Строгие имена могут быть получены с помощью программы SN.exe, используемой для создания ключевого файла (keyfile), который, в свою очередь, генерирует во время компиляции строгое имя компонента.
Помещение в глобальный кэш сборок Для того чтобы использовать компонент .NET Framework из приложения или компонента СОМ, его нужно инсталлировать в глобальный кэш сборок с помощью утилиты компоновщика сборок AL.exe (Assembly Linker Utility). Использование компонентов .NET Framework в СОМ-приложениях
199
Регистрация Перед тем как компонент .NET Framework будет вызван из неуправляемого кода СОМ, его необходимо зарегистрировать в системном реестре. Регистрация компонента происходит с помощью утилиты регистрации сборки RegAsm.exe. Кроме того, утилита RegAsm.exe позволяет создавать и регистрировать библиотеку типов TypeLib.
Создание библиотеки типов Для создания ранних связей с компонентами .NET Framework следует создать библиотеку типов (TypeLib). Для этого существует несколько способов: •
с помощью утилиты экспорта библиотеки типов TlbExp.exe;
•
с помощью класса S y s t e m . R u n t i m e . I n t e r o p S e r v i c e s . T y p e L i b C o n v e r t e r ;
• с помощью Visual Studio.NET при наличии ссылки на компонент СОМ. Интерфейс технологии COM I D i s p a t c h позволяет создавать позднее связывание между СОМ-клиентом и компонентом .NET. Поддержка интерфейса I D i s p a t c h автоматически обеспечивается единой средой исполнения (CLR). Это одно из условий, позволяющее CLR создавать библиотеку типов, благодаря которой обеспечивается реализация I D i s p a t c h .
Сквозной контроль В листинге 12.11 приведен пример класса Employee, который используется для сквозного контроля процесса вызова компонента .NET Framework из неуправляемого кода. ЛИСТИНГ 12.11. Компонент .NET Framework, используемый технологией СОМ Public Class Employee Private c_sFirstName As String Private c_sLastName As String Private c_sSSN As String Public Property FirstNameO As String Get Return c_sFirstName End Get Set(ByVal Value As String) c_sFirstName = Value End Set End Property Public Property LastNameO As String Get Return c_sLastName End Get Set(ByVal Value As String) c_sLastName = Value End Set End Property Public Property SSN() As String Get Return c_Sssn End Get Set(ByVal Value As String) c_sSSN = Value End Set
200
Глава 12. Взаимодействие элементов языка
End Property Public Function ReverseString(ByVal TheString As String) As String Dim sReversedString As String Dim i As Integer For i = TheString.Length - 1 To 0 Step -1 sReversedString = sReversedString & TheString.Substring(i, 1) Next Return sReversedString End Function End Class Перед компиляцией того или иного компонента должен быть создан ключевой файл, позволяющий компилировать указанный компонент со строгим именем. Сейчас попробуем вызвать типичное строгое имя C o m l n t e r o p . SNK. Для этого необходимо открыть окно командной строки и в каталоге BIN проекта выполнить следующую команду: SN.EXE -k Comlnterop.SNK Теперь, после создания строгого имени, загрузите Visual Studio.NET, щелкните правой кнопкой мыши на имени проекта в окне Solution Explorer и откройте страницу свойств проекта (рис. 12.1). Из списка Common Properties выберите элемент Sharing, установите флажок Generate Strong Name Using, активизируйте переключатель Key File и введите имя ключевого файла (или же воспользуйтесь списком для поиска нужного файла). В данном примере этим файлом является C o m l n t e r o p . SNK. Теперь остается создать компонент. VBDotNetForDeveo l pers Property Pages l
An assembly needs a strong name to be instated into the global cache, or to be used from a shared location outside of the appkatton dbectory. Specify the originator toy used to generate the strong name. (7 Generate strong name tsingt • ••
'
j Comlrir.erop.snk *"* Key container':
Help
Рис. 12.1. Назначение строгого имени в Visual Studio.NET
После выполнения приведенных действия создана библиотека DLL, необходимая для регистрации (а также создания библиотеки типов TypeLib) и помещения в глобальный кэш сборок. Введите в командную строку следующее: RegAsm Comlnterop.Dll /tlb:Comlnterop. Tib
Использование компонентов .NET Framework в СОМ-приложениях
201
Далее необходимо инсталлировать компонент в глобальный кэш сборок, для чего следует воспользоваться командой AL.Exe /i:ComInterop.Dll Теперь компонент полностью готов для использования из неуправляемого кода СОМ. Попытайтесь воспользоваться этим компонентом с помощью Visual Basic 6.0 или VBA. Пример программного кода Visual Basic 6.0 приведен в листинге 12.12. (Прежде всего следует создать ссылку на библиотеку типов.) Листинг 12.12. Вызов компонента .NETв Visual Basic 6.0 Dim oEmployee as Comlnterop.Employee Dim sReversedString as String Set oEmployee = New Comlnterop.Employee oEmployee.FirstName = "DotNet" oEmployee.LastName = "Guru" sReversedString = "Hello World" Debug.Print oEmployee.FirstName Debug.Print oEmployee.LastName Debug.Print oEmployee.ReverseString(sReversedString)
Использование компонентов COM из приложений .NET Framework Один из наилучших методов перемещения приложений в .NET Framework состоит в замене компонентов приложений, что позволяет использовать существующие компоненты СОМ из кода .NET Framework. Обратите внимание, что использовать компоненты СОМ из приложений .NET Framework гораздо проще, чем компоненты .NET Framework из СОМ. Когда код .NET Framework создает экземпляр неуправляемого объекта СОМ, объявление созданного объекта происходит с помощью упаковщика. В данном случае используется упаковщик времени выполнения (Runtime Callable Wrapper— RCW), действующий в качестве "заместителя" существующего неуправляемого объекта. По отношению к коду .NET Framework упаковщик RCW появляется в качестве всего лишь управляемого компонента .NET. Но его единственная цель состоит в правильной передаче вызовов между кодом .NET Framework и неуправляемым компонентом СОМ. Каждый экземпляр СОМ-объекта содержит только один RCW, независимо от количества существующих ссылок на неуправляемый объект СОМ. Практически всю "черновую" работу неуправляемого компонента СОМ в .NET Framework среда разработки Visual Studio.NET берет на себя. Например, при выборе одного из компонентов СОМ в диалоговом окне Add Reference Visual Studio.NET автоматически выполнит утилиту импорта библиотеки типов Tlplmp.exe, которая, в свою очередь, создаст сборку, содержащую все метаданные, требующиеся .NET Framework для использования неуправляемого компонента СОМ. На рис. 12.2—12.4 и в листинге 12.13 иллюстрируется процесс создания приложения Windows, в котором для получения доступа к SQL Server и загрузки списка используется ADO 2.6. Итак, сначала необходимо создать новое приложение Windows. После этого щелкните правой кнопкой мыши на объекте References, который находится в окне Solution Explorer, и добавьте ссылку в появившемся диалоговом окне Add Reference (см. рис. 12.2). 202
Глава 12. Взаимодействие элементов языка
Mc i rosoft Actvie Server Pages Obe j c.5.0.2037.1 Mc i rosoft ActrveMove i Control 2.0.0.0 Mc i rosoft ActvieX Data Obe j cts (Mult.2.60.6526.0 Mc i rosoft ActvieX Data Obe j cts (Mult.2.60.6526.0 Mc i rosoft ActvieX Data Obe j cts 2.0 L.2.60.6526.0 Mc i rosoft ActvieX Data Obe j cts 2.1 L2.60.6526.0 . Mc i rosoft ActvieX Data Obe j cts 2.5 L.2.60.6526,0 Mc i rosoft ActvieX Data Obe j cts 2.6 L.2.60.6526.0 Mc i rosoft Actvies Data Obe j cts Reco.2.60,6526.0 Mc i rosoft ActvieX Data Obe j cts Reco.2.60.6526.0
D:\WINNl\5yst em32\inetsi DAWINNT\System32\amco D:\Prograrn Fi!es\Common I j D:\Procjram Files\Common I D:\Prograni Files\Ccmrion I D:\Program Files\Common 1 D:\Program Ftles\Common I D:\ProgtarriFiles\Cornmonl D:\Prograrn Fi!es\Common I D:\Program Files\Common I t
ш ж
SC eo lc e tdponeC om poe nen st: 1Type J Souc m n t N a m ree :o ra c rjm ts F C \iommon|Fe ls\. M cirosotfAvce itXDaa t OA be v c je itcX ts. D\P He pl Puc. 12.2. Диалоговое окно Add Reference, содержащее ссылку на компонент ADO 2.6
В списке вкладки СОМ диалогового окна Add Reference выделите компонент ADO 2.6 (см. рис. 12.3). -X] N . ET Framework. COM I Projects Component Name Verso in Mc i rosoft Actvie Server Pages Obe j.c.5.0.2037.1 Mc i rosoft ActvieMove i Control 2,0.0.0 Mc i rosoft ActvieX Data Obe j cts (Mut. . 2.60,6526.0 Mc i rosoft ActvieX Data Obe j cts (Mul.t.2.60.6526.0 Mc i rosoft ActvieX Data Obe j cts 2.0.L2..60.6526.0 Mc i rosoft ActvieX Data Obe j cts 2.1.L2..60.6526.0 Mc i rosoft ActvieX Data objects 2,5 L ..2.60.6526.0 Mc i rosoft ActvieX Data objects Reco ..2.60.6526,0 Mc i rosoft ActvieX Data Obe j cts Rec.o2 ..60.6526.0 See l cted Components: Component Uame
Теперь перетащите на форму список и кнопку. Размеры элементов и их расположение должны соответствовать показанным на рис. 12.4. Присвойте кнопке имя btnLoad, а списку — имя lstPublishers.
Перейдите в окно программы и введите код из листинга 12.13. (Измените информацию соединения в соответствии с параметрами сервера вашей базы данных.)
Использование компонентов .NET Framework в СОМ-приложениях
203
Chapter! 2А00!н1игир -Microsoft VisualBesic.NET[design] -Form.. File |d* View Protect guiW Debug Format Toots W»wV>w Help 1С 11& * -311 W «> & | S О ?В ffi i«" Jft «5
Puc. 12.4. Стандартная форма Windows в процессе разработки
ЛИСТИНГ 12.13. Заполнение окна списка данными, полученными из базы да
Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoad.Click Dim oPublishersRecordset As ADODB.Recordset Dim oPubsConnection As ADODB.Connection Dim sPubsConnection As String = "Provider=SQLOLEDB,1;Password='';" & "Persist Security Info=True;User ID=sa;Initial Catalog=pubs;" & "Data Source=red-leader2" Dim sGetPublisher As String = "Select pub_name from publishers " & "order by pub_name" oPubsConnection = New ADODB.Connection () oPubsConnection.ConnectionString = sPubsConnection oPubsConnection.Open () oPublishersRecordset = New ADODB.Recordset() oPublishersRecordset.Open(sGetPublisher, oPubsConnection, ADODB.CursorTypeEnum.adOpenForwardOnly, ADODB.LockTypeEnum.adLockReadOnly) Do Until oPublishersRecordset.EOF lstPublishers.Items.Add( oPublishersRecordset.Fields("pub_name").Value.ToString) oPublishersRecordset.MoveNext () Loop oPublishersRecordset.Close() oPubsConnection.Close() End Sub
204
Глава 12. Взаимодейспъие элементов языка
Теперь запустите приложение и щелкните на кнопке btnLoad. Окно приложения примет вид, как на рис. 12.5. Среда .NET Framework предоставляет механизмы, •7Й ADO2.6 Interop используемые для вызова неуправляемых компонентов Algodata Infosystems СОМ в режиме позднего связывания и позволяющие Binnet&Hatdley Five Lakes PublisNng применять дополнительные интерфейсы компонентов. GGG&G Lucerne Publishing В VB.NET, как и в предыдущих версиях языка, в проNew Moon Books Ramona Publishers цессе создания объектов активное участие принимает Scootney Books оператор CreateObj e c t . В языке VB.NET применение оператора C r e a t e O b j e c t ограничено созданием объектов ActiveX (или классов .NET Framework, объявленных как объекты ActiveX). Кроме этого, оператор C r e a t e O b j e c t в VB.NET поддерживает необязаload list тельный параметр, содержащий имя сервера, на котором запущен компонент. Рис. 12.5. Форма Windows, заполПри использовании компонентов СОМ из VB.NET, а ценная данными также при проектировании компонентов, которые будут использоваться VB.NET, следует обратить внимание на выполнение процесса очистки. Для этого лучше воспользоваться одним из методов, которые поддерживают сборку мусора в среде .NET Framework. Все существующие ссылки компонента СОМ содержатся в вызываемом упаковщике CCW, который при выходе из области действия не уничтожается. Именно поэтому, как показано в листинге 12.13, пришлось явно закрыть соединение и набор записей. Данные компоненты используют ресурсы системы, поэтому не нужно ждать, когда произойдет их очистка с помощью сборки мусора. Если вы используете компоненты СОМ, содержащие метод (или методы) очистки, воспользуйтесь этим методом (или метода-1 ми). Также не забудьте при разработке компонента СОМ добавить к нему метод очистки.
Службы СОМ+ Службы СОМ+ представляют собой достаточно мощные инструменты, используемые при разработке масштабируемых приложений .NET Framework. Для создания масштабируемых приложений, независимо от того, являются ли они приложениями ASP.NET, Web-службами или, например, распределенными приложениями Windows, следует воспользоваться преимуществами тех служб, которые предоставлены в СОМ+.
Применение служб СОМ+ В первую очередь необходимо понять, какие же службы обеспечивает СОМ+ для приложений .NET Framework. Службы СОМ+ поддерживаются сервером транзакций Microsoft (MTS), который представлен в 1997 году. MTS обеспечивает среду выполнения для компонентов. Многие пользователи, обратив внимание на имя сервера, пришли к выводу, что это процессор транзакций, хотя фактически он обеспечивает управление ресурсами компонентов. К управлению ресурсами, которые обеспечивает MTS, можно отнести управление транзакциями, организацию пула и многократное использование потоков, организацию пула подключений к базам данных, а также многократное использование (но не объединение) объектов. Транзакции могут охватывать различные типы управления ресурсами, например SQL Server, Oracle, DB2 или очередь сообщений Microsoft (Microsoft Message Queue — MSMQ). При создании операционной системы Windows 2000 компания Microsoft значительно расширила MTS, в результате появились службы СОМ+. Существует несколько моментов, на которые следует обратить внимание. Прежде всего службы, обеспечиваемые MTS, были интегСлужбы СОМ+
205
рированы в операционную систему. Кроме этого, службы СОМ+ были существенно обновлены, что позволило повысить масштабируемость, эффективность и стабильность выполнения распределенных приложений. Краткое описание служб СОМ+ приведено в табл. 12.2. Таблица 12.2. Службы СОМ+, реализованные в Windows 2000 Служба
Описание
Службы транзакций
Обеспечивает службы и диспетчер ресурсов для управления транзакциями к базе данных и другим источникам данных без ресурсного программирования
Автоматические транзакции
Обеспечивает службам транзакции декларативный синтаксис вместо методов, созданных на основе "ручного" кода
Многократное использование и организация пула объектов
Обеспечивает возможность создания пула многократно используемых объектов
Организация очереди компонентов
Обеспечивает возможность выполнения методов компонентов, которые фактически выполняются в какое-либо другое время
Активизация по требованию
Для максимальной масштабируемости обеспечивает механизм создания объектов (или многократного использования уже существующих объектов) при вызове того или иного метода и освобождения объекта при завершении выполнения данного метода
Синхронизация
Обеспечивает параллельное управление
Общедоступные свойства
Совместно использует состояние различных экземпляров объектов в пределах серверного процесса
Многократное использование пула потоков
Для максимальной масштабируемости обеспечивает службу, позволяющую для выполнения компонента вместо постоянного создания и уничтожения созданных потоков многократно использовать потоки, а также поддерживать пул потоков
Организация пула подключений
Для достижения максимальной масштабируемости базы данных обеспечивает службу, позволяющую многократно использовать подключения к базе данных, которые совместно используют одни и те же параметры, вместо создания новой связи для каждого действия базы данных
Декларативная конструкция
Обеспечивает механизм, который предоставляет компонентам конструктивную информацию вместо формирования указанной информации внутри компонента
Безопасность, основанная Обеспечивает гибкий механизм, определяющий полномочия доступа той или иной группы пользователей на ролевом принципе Позволяет выполнять транзакции без привлечения необходимых реКомпенсация ресурсов сурсов
Для компонентов, инсталлированных как приложения СОМ+, некоторые из служб активизируются автоматически. К числу автоматически выполняемых служб относятся синхронизация и многократное использование и организация пула потоков.
Написание компонентов .NET Framework, которые взаимодействуют со службами СОМ+ Взаимодействие .NET Framework и сервисов СОМ+ выполняется большей частью с помощью атрибутов. Атрибуты используются для инсталляции приложений в каталог СОМ+, вывода данных транзакции, определения свойств пула объектов и др. Остальные 206
Глава 12. Взаимодействие элементов языка
возможности взаимодействия реализованы с помощью ряда классов пространства имен System.EnterpriseServices.
Инсталляция приложений в каталог СОМ+ В приложениях .NET Framework могут применяться традиционные компоненты СОМ или компоненты .NET Framework, использующие службы СОМ+. Кроме этого, компоненты .NET Framework могут устанавливаться в службы СОМ+, которые, в свою очередь, могут использоваться приложениями .NET Framework или традиционными приложениями, созданными на основе технологии СОМ. Использование компонентов СОМ из приложений .NET Framework и, соответственно, компонентов .NET Framework из приложений СОМ описывается в следующем разделе. Для того чтобы использовать службы СОМ+ в компоненте .NET Framework, необходимо добавить информацию об этом компоненте в каталог СОМ+. Чтобы инсталлировать компонент .NET Framework в каталог СОМ+, следует выполнить несколько действий. Сначала нужно получить с помощью атрибутов информацию, относящуюся к тому приложению СОМ+, в котором будет инсталлирован компонент .NET Framework. Атрибуты, позволяющие выполнить эту операцию, размещены в пространстве имен System. E n t e r p r i s e S e r v i c e s . Атрибуты приложения приведены в табл. 12.3. Таблица 12.3. Основные атрибуты приложения СОМ+, размещенные В
System.EnterpriseServices
Атрибут ApplicationName
Назначение Используется для присвоения имени приложению СОМ+, в котором инсталлированы компоненты сборки
Applications
Определяет GUID приложения СОМ+
ApplicationActivation
Указывает, будет ли данный компонент активизирован в выделенном серверном процессе или же в процессе разработчика
ApplicationAccessControl
Позволяет настроить конфигурацию безопасности библиотеки
ApplicationQueuing
Обеспечивает поддержку организации очереди компонентов
или серверного приложения, содержащего приложение Description
Описание приложения
AssemblyKeyFileAttribute
Ключевой файл строгого имени (обязательный)
Все атрибуты приложения используются на уровне сборки, что позволяет определить приложение, в которое будут инсталлированы компоненты. Инсталляция компонента происходит автоматически при первом запуске компонента приложением .NET Framework. При первой загрузке сборки будет обнаружено, что она наследуется из класса System. ServicedComponent. Поэтому будет использована информация, необходимая для инсталляции компонента в каталог служб СОМ+ и глобальный кэш сборок. Поскольку компонент будет установлен в глобальный кэш сборок, потребуется атрибут Assemb l y K e y F i l e A t t r i b u t e . В том случае, если компонент .NET Framework должен быть инсталлирован предварительно, т.е. до первого запуска, что требуется, например, для его использования приложением СОМ, воспользуйтесь утилитой RegSvcs.exe. Эта утилита может быть использована для регистрации компонента .NET Framework в каталоге СОМ+ вместе с информацией, содержащейся в метаданных сборки. Атрибуты приложения должны быть первыми элементами файла компонента. В листинге 12.14 приведен
Службы СОМ+
207
пример атрибутов уровня сборки компонента .NET Framework, инсталлированного в приложение СОМ+. Листинг 12.14. Инсталляция компонента .NET Framework в службы СОМ+
В приведенном коде создается приложение СОМ+ Employee Data Access, имеющее идентификатор ffdc6a80-d527-lldO-a32c-34afO6clOOOO. Приложение будет выполняться в выделенном серверном процессе: для этого загружается система безопасности и реализуется поддержка компонентов с организацией очереди. Для определения свойств атрибута воспользуйтесь методо,м, который основан на параметрах имени. В качестве примера использования данного метода можно привести последнюю строку листинга 12.14:
ApplicationQueuing(Enabled:=True)>
Эта строка иллюстрирует присвоение значения True свойству ApplicationQueuing. Enabled.
Использование транзакций СОМ+ с компонентами .NET Framework Что же произойдет после инсталляции приложения в каталог СОМ+? Рассмотрим процесс конфигурирования транзакций СОМ+. Прежде всего, все компоненты, которые будут включены в службы СОМ+, должны наследоваться из S y s t e m . S e r v i c e d C o m p o n e n t . После выполнения этого требования необходимо обеспечить атрибуты на уровне метода и класса. Доступные атрибуты транзакции приведены в табл. 12.4. Таблица 12.4. Основные атрибуты транзакции EnterpriseServices Атрибут Transaction
Назначение Указывает тип поддержки транзакции, обеспечиваемой компонентом
AutoComplete
Отмечает, что методом компонента назначен A u t o C o m p l e t e . Это означает, что при возникновении исключительной ситуации будет вызван S e t A b o r t . В противном случае будет вызван S e t C o m p l e t e J u s t i n T i m e A c t i v a t i o n Для того чтобы использовать A u t o C o m p l e t e , необходимо также установить J u s t l n T i m e A c t i v a t i o n
Компоненты служб СОМ+ имеют определенное свойство настройки транзакций, которому может быть присвоено одно из следующих значений: •
Disabled;
•
None;
•
Required;
• RequiresNew; • 208
Supported. Глава 12. Взаимодействие элементов языка
Для определения настройки транзакции компонента .NET Framework воспользуйтесь атрибутом транзакции, а также перечислителем T r a n s a c t i o n O p t i o n . Пример описаний класса с различными параметрами транзакции приведен в листинге 12.15. Листинг 12.15. Определение параметров транзакции •«Transaction(TransactionOption.Supported)> _ Public Class DataAccess End Class В листинге 12.16 два атрибута определены в классе DataPersistance. Листинг 12.16. Определение двух атрибутов •«Transaction Public Class DataPersistance End Class Теперь, после выполнения настройки транзакции компонента, следует присвоить значение AutoComplete отдельным методам. Это может быть выполнено с помощью AutoCompleteAttribute (листинг 12.17). Листинг 12.17. Использование атрибута AutoCoapleteAttrxbute Public Function GetEmployees() As DataSet End Function В качестве одного из вариантов существует возможность ручной обработки процесса транзакции с помощью объекта C o n t e x t U t i l , который обеспечивается при наследовании из System. ServicedComponent. Для указания того, что данный метод успешно завершен, используется следующий код: ContextUtil.SetComplete() Чтобы показать некорректность выполнения и завершить транзакцию, можно воспользоваться следующим выражением: ContextUtil.SetAbort () Класс C o n t e x t U t i l предоставляет ряд хорошо знакомых транзакций (если вы, конечно, знакомы с транзакциями служб СОМ+), а также контекстные связанные методы и свойства. К числу известных методов и свойств класса C o n t e x t U t i l относятся I s I n T r a n s a c t i o n , EnableCommit, DisableCommit, OriginalCallerName и I s C a l l e r l n R o l e . В более сложных сценариях, например при использовании системы безопасности на основе ролей СОМ+, для более устойчивой защиты следует использовать класс C o n t e x t U t i l . В свою очередь, для существующего простого сценария использование метода AutoComplete значительно упрощает программирование транзакции. Остается только отметить методы, которые являются методами AutoComplete, ввести при необходимости обработку исключительных ситуаций и благополучно завершить выполнение сценария.
Организация пула объектов в компонентах .NET Framework Одной из новых возможностей служб СОМ+, которые не были доступны для разработчиков предыдущих версий Visual Basic, является организация пула объектов. Visual Basic 5.0 и 6.0 позволяет создавать только неподдерживаемые СОМ-объекты, "живущие" в отдельном потоке. VB.NET создает свободные или многопоточные компоненты, которые представляют собой самую лучшую потоковую модель для организации пула объектов.
Службы СОМ+
209
Объединение объектов позволяет разработчикам получить доступ к службам СОМ+, образующим пул обрабатываемых объектов данного типа, которые, в свою очередь, обслуживают запросы всех методов, вызываемых объектом. В некоторых случаях это гораздо лучше, чем постоянное многократное создание объектов, что происходит, например, при непосредственной активизации. Чаще всего фактическое создание объектов значения не имеет. В тех случаях, когда создание реального объекта требует выполнения большого объема работы, на помощь приходит пул объектов. Например, приложение страхования может содержать в базе данных таблицу коэффициентов. Эти коэффициенты практически не изменяются, но используются достаточно часто. При выполнении непосредственной активизации происходит создание компонента, организация доступа к базе данных для ввода коэффициентов и вызов метода, использующего данные коэффициенты в процессах различных типов. Каждое обращение к объекту данного типа приведет к поиску подобной информации в базе данных. В этой ситуации поможет организация пула объектов. Объявите, что компонент существует в пуле и структуре кода; это позволит загрузить однажды обработанные данные и в дальнейшем применять при каждом обращении к методу, в котором они используются, объединенную версию объекта. Особое внимание следует обратить на реализацию объекта. Постарайтесь сделать так, чтобы в промежутках между обращениями состояние оставалось неизменным. Другими словами, зачем вам нужен метод, изменяющий данные и не возвращающий их в предыдущее состояние. Для данных, которые изменяются редко и используются только для чтения, наилучшим вариантом будет организация пула объектов. В этом случае будет выполнен целый ряд экземпляров класса, поэтому вполне понятно стремление сохранить состояние неизменным и не зависящим от того, какой из экземпляров будет задействован программным кодом во время создания запроса. Для использования пула объектов в СОМ необходимо реализовать интерфейс I O b j e c t C o n t r o l . Интерфейс I O b j e c t C o n t r o l содержит три метода: A c t i v a t e , D e a c t i v a t e и CanBePooled. В .NET Framework интерфейс I O b j e c t C o n t r o l существует в пространстве имен System. E n t e r p r i s e S e r v i c e s s , но лучший вариант использования I O b j e c t C o n t r o l состоит в замещении базового класса реализацией трех методов, участвующих в организации пула объектов. Эти методы предоставляют возможность выполнения настройки и очистки состояния, а также вывода сообщения о том, что данный экземпляр пулом более не используется.
Метод Activate При использовании объекта из пула службами СОМ+ вызывается метод I O b j e c t C o n t r o l . A c t i v a t e . Этот метод выполняет определенные действия для получения в соответствующем порядке состояния любых вызываемых методов. В классе ServicedComponent таким методом является A c t i v a t e .
Метод Deactivate С помощью метода I O b j e c t C o n t r o l . D e a c t i v a t e можно выполнить очистку кода, что позволяет следующему пользователю объекта получить объект в достоверном состоянии. Таким методом в классе ServicedComponent является D e a c t i v a t e .
Метод CanBePooled Метод IOb j e c t C o n t r o l . CanBePooled позволяет определить, что тот или иной экземпляр объекта может быть помещен в пул. В том случае, если объект может быть помешен в пул, данный метод возвращает значение True, в противном случае — значение F a l s e . В классе ServicedComponent таким методом является CanBePooled. 210
Глава 12. Взаимодействие элементов языка
Организация пула объектов в VB.NET В языке VB.NET метод, использующий организацию пула объектов, реализуется с помощью атрибутов, а также замещения методов базового класса. Атрибут пула объектов помещен в определение класса. В листинге 12.18 приведен пример класса, использующего пул объектов, а также заданы основные параметры пула: размер пула изменяется от 2 до 10 экземпляров, а временной лимит равен 20 миллисекундам. Класс содержит метод, используемый для извлечения набора данных D a t a S e t ADO.NET и его хранения в переменной уровня класса. После того как необходимые данные будут однажды извлечены, при каждом последующем обращении к методу будет возвращен существующий набор данных DataSet. Реализация интерфейса I O b j e c t C o n t r o l достаточно стандартна: метод CanBePooled возвращает логическое значение T r u e , при выполнении методов A c t i v a t e или D e a c t i v a t e не происходит практически ничего. Листинг 12.18. Класс, поддерживающий организацию пула объектов Public Class PooledEmployees I n h e r i t s ServicedComponent Private m_oEmployees As DataSet Public Function GetEmployees() As DataSet Dim oDA As DataAccess If m_oEmployees Is Nothing Then oda = New DataAccess() m_oEmployees = oda.GetEmployees() End If Return m_oEmployees End Function Public Overrides Sub Activate () End Sub Public Overrides Function CanBePooled() As Boolean Return True End Function Public Overrides Sub Deactivate() End Sub End Class
Использование строк конструктора с компонентами .NET Framework Одним из наименее сложных, но в то же время наиболее функциональных сервисов, появившихся в службах СОМ+, является возможность передачи строки, присутствующей в конструкции компонента. Чаще всего строки конструктора используются в компонентах доступа к данным для передачи строки подключения в базу данных. В прошлом для создания строки подключения применялись самые разные методы, например строгое программирование (достаточно высокая эффективность, но низкая гибкость), использование DSN, т.е. имени источника данных (низкая эффективность), хранение в системном реестре (низкая эффективность), а также использование для хранения информации текстового файла определенного формата (низкая эффективность). Чаще всего применялся один из перечисленных методов, после чего созданная строка сохранялась для всеобщего доступа.
Службы СОМ+
211
Теперь при использовании строк конструктора выбор базы данных (или каких-либо иных параметров конфигурации, заданных администратором в каталоге COM4-) будет занесен в память и передан компонентам. Строки конструктора, как и организация пула объектов, содержат атрибут, размещенный в классе, и замещают метод C o n s t r u c t базового класса. Пример использования строки конструктора приведен в листинге 12.19. Листинг 12.19. Класс, использующий строки конструктора Public Class ObjectConstruction Inherits ServicedComponent Private c_sConstructString As String Public Overrides Sub Construct(ByVal constructString As String) c_sConstructString = constructString End Sub Public Function GetConstructionString() As String GetConstructionString - c_sConstructString End Function End Class
Для того чтобы можно было воспользоваться строками, класс должен использовать атрибут C o n s t r u c t i o n E n a b l e d . Как следует из приведенного примера, конструкция активизируется и по умолчанию ей присвоено значение ( L o c a l ) . Во время загрузки экземпляра класса COM4- вызывает метод C o n s t r u c t , передающий строку конструктора. Эта модель значительно отличается от применяемой в Visual Basic 6.0, в которой класс для использования строки конструктора должен выполнить ЮЬ j e c t C o n s t r u c t .
Использование компонентов с организацией очереди с .NET Framework В службах СОМ+ используется концепция компонентов с организацией очереди. Такие компоненты представляют собой мощный механизм асинхронного вызова компонентов. Разработчики получили возможность создавать используемые в том или ином процессе компоненты, немедленное выполнение которых не является обязательным. Для записи всех действий, которые применялись к созданному компоненту, данный сервис использует очередь сообщений Microsoft (MSMQ). При выполнении процесса компонента MSMQ воспроизводит записанные действия, а компонент, в свою очередь, их обрабатывает. Для разработчика фактический вызов методов и назначение свойств практически не отличается от операций, выполняющихся при использовании стандартного компонента. Существуют атрибуты, взаимодействующие с компонентами с организацией очереди. Эти атрибуты представлены в табл. 12.5. Таблица 12.5. Атрибуты компонентов с организацией очереди служб СОМ+ Атрибут
Назначение
A p p l i c a t i o n Q u e u i n g Допускает поддержку компонента с организацией очереди в сборке i n t e r faceQueuing
Допускает поддержку компонента с организацией очереди в интерфейсе
Пример класса, поддерживающего организацию очередей, приведен в листинге 12.20.
Листинг 12.20. Класс .NETFramework, поддерживающий организацию очередей
212
Глава 12. Взаимодействие элементов языка
Public Interface IQueuedDataPersistance Sub SaveEmployee(ByVal SSN As String, ByVal FirstName As String, _ ByVal LastName As String, ByVal Title As String, ByVal Address As String, ByVal City As String, ByVal State As String, ByVal Zip As String, ByVal Picture As String) End Interface Public Class QueuedDataPersistance Inherits ServicedComponent Implements IQueuedDataPersistance Public Sub SaveEmployee(ByVal SSN As String, ByVal FirstName As String, ByVal LastName As String, ByVal Title As String, ByVal Address As String, ByVal City As String, ByVal State As String, ByVal Zip As String, ByVal Picture As String) Implements IQueuedDataPersistance.SaveEmployee End Sub End Class Полная регистрация сборки в этот пример не вошла. Данный пример включает только разрешение поддержки компонентов с организацией очереди. Сборка, поддерживающая организацию очередей, может содержать как компоненты с организацией очереди, так и стандартные компоненты. Как видно из приведенного кода, интерфейс IQueuedDataPersistance отмечен в качестве допускаемого для выполнения с организацией очереди. Для того чтобы использовать компоненты с организацией очереди, необходимо определить данный интерфейс, отметить его в качестве допускаемого для выполнения с организацией очереди и, конечно же, реализовать его.
Использование службы событий СОМ+ Возможно, одной из наиболее сложных служб СОМ+ является служба слабосвязанного события (Loosely Coupled Event Service — LCE). Служба LCE позволяет разработчику создать механизм трансляции сообщений подписчикам сети. В предыдущих версиях Visual Basic поддержка LCE обеспечивалась следующим образом. Создайте интерфейс, который полностью состоит из процедур. Этот интерфейс станет классом Event; процедуры, в свою очередь, станут событиями. Скомпилируйте этот класс в виде DLL, что позволит инсталлировать его в каталог СОМ+. В приложении СОМ+ запустите мастер создания компонента. Во время работы мастера выберите инсталляцию нового класса Event. Укажите в окне просмотра расположение компилированной библиотеки DLL, что позволит инсталлировать ее как класс E v e n t . После этого подписчики должны реализовать интерфейс, определенный в классе Event, и присоединиться к событию. Подсоединение к событию может быть осуществлено с помощью средств управления службами сервисов компонентов СОМ+ для компонентов, инсталлированных в каталог СОМ+, или же выполнено с помощью программного кода. После того как подписки будут выполнены, а события задействованы другим процессом, произойдет обработка экземпляра класса Event и вызов одного из событий. После этого будут вызваны все подписчики данного события. Процесс, происходящий в .NET Framework, точно такой же. Единственное отличие состоит в том, что для создания класса Event в .NET Framework используется атрибут, указывающий, что данный класс является классом Event. Пример класса Event приведен в листинге 12.21.
Службы СОМ+
213
Листинг 12.21. Пример класса Event Public Interface IEmployeeEvents Sub EmployeeSaved() End Interface Теперь класс должен объявить интерфейс события. В листинге 12.22 приведен пример класса, реализующего интерфейс объявления события, определенного в листинге 12.21. Листинг 12.22. Класс Event <EventClass(AllowInProcSubscribers:=False, FirelnParallel:=True)> Public Class EmployeeEvents Inherits ServicedComponent Implements IEmployeeEvents Public Sub EmployeeSaved() Implements IEmployeeEvents.EmployeeSaved End Sub End Class После того как событие было объявлено, оно может использоваться другим классом. Для этого данный класс должен реализовать интерфейс события. В листинге 12.23 приведен пример класса L i s t e n e r . Листинг 12.23. Приемник клиента CodeEvent Public Class EmployeeClient Inherits ServicedComponent Implements IEmployeeEvents Public Sub EmployeeSaved() Implements IEmployeeEvents.EmployeeSaved End Sub End Class Слабосвязанные события являются достаточно мощным средством, хотя и могут быть неверно истолкованы при первом рассмотрении.
Ролевая система безопасности Впервые была представлена вместе с сервером транзакций Microsoft (MTS). Эта система предоставляет обладающий широкими возможностями декларативный и программируемый метод, используемый для определения пользовательских прав на выполнение того или иного действия. Пример простого компонента, использующего ролевую систему безопасности, приведен в листинге 12.24. Листинг 12.24. Система безопасности, основанная на ролевом принципе <SecurityRoleAttribute("Administrator")> _ public class RoleBasedSecurity Inherits ServicedComponent Public Function AmIInThisRole(ByVal RoleName As String) As Boolean Try If Not ContextUtil.IsSecurityEnabled Then Return False Else If ContextUtil.IsCallerlnRole(RoleName) Then Return True Else Return False End If End If 214
Глава 12. Взаимодействие элементов языка
Catch exp As Exception Return False End Try End Function End Class <SecurityRoleAttribute("Administrator")> public class RoleBasedSecurity Inherits ServicedCoraponent
Компенсация ресурсов Иногда возникают ситуации, требующие использования в компоненте различных операций, подобных транзакциям. Основная проблема может состоять в том, что ресурс, которому вы пытаетесь предоставить управление с помощью транзакции, не поддерживает транзакции СОМ+. Для того чтобы выйти из подобного положения, в СОМ+ разработана концепция компенсации ресурсов. В листинге 12.25 приведен пример класса, требующего использования транзакции, а в листинге 12.26 — пример компенсации ресурсов для этого класса. Листинг 12.25. Класс, требующий использование транзакции Public Class TestWorker Inherits ServicedComponent Private c_clerk As CRM.Clerk Public Sub New() c_clerk = New CRM.Clerk(GetType(CRMCompensator) , ".NET CRM Sample", CRM.CompensatorOptions.AllPhases) End Sub . Public Sub DeleteFile(ByVal msg As String) If System.10.File.Exists(msg & ".crmTmp") Then c_clerk.ForceTransactionToAbort()z Else c_clerk.WriteLogRecord(msg) c_clerk.ForceLog() Try File.Move(msg, msg & ".crmTmp") Catch c_clerk.ForceTransactionToAbort() End Try End If End Sub Public Sub Commit() ContextUtil.SetComplete() End Sub Public Sub Abort() ContextUtil.SetAbort() End Sub End Class Ресурс, используемый в листинге 12.25, собственного администратора транзакции не имеет, поэтому в листинге 12.26 определяется компенсация ресурса. Листинг 12.26. Компенсация ресурса Службы СОМ+
215
Imports Imports Imports Imports Imports Imports
System.ComponentModel System System.10 System.Reflection System.EnterpriseServices CRM = System.EnterpriseServices.CompensatingResourceManager
Public Class CRMCompensator Inherits ServicedComponent Public Override Function CommitRecord(ByRef rec as CRM.LogRecord) _ as Boolean Try File.Delete(rec.Record & ".crmTmp") MsgBox("Deleted", rec.Record & ".crmTmp") Catch MsgBox("Could not deleted", rec.Record & ".crmTmp") End Try Return False End Function public Override AbortRecord(ByRef rec as CRM.LogRecord) as Boolean Try File.Move(rec.Record+".crmTmp", CTYPE(rec.Record,String) MsgBox("Aborting delete", CTYPE(rec.Record,String) Catch MsgBox("Could not abort delete", CTYPE(rec.Record,String) .End Try Return false End Function End Class
Резюме Компания Microsoft создала обладающую очень широкими возможностями модель, которая позволяет взаимодействовать с компонентами СОМ и компонентами, созданными на основе API. Кроме того, благодаря такой схеме взаимодействия можно использовать службы СОМ+ из компонентов .NET Framework, а также компоненты .NET Framework из СОМ-приложений. Постарайтесь перед использованием API Windows выяснить, не существует ли способа выполнения подобной задачи с помощью средств .NET Framework. Среда .NET Framework предоставляет множество различных параметров и утилит, гарантирующих, что почти все создаваемые компоненты .NET Framework могут использоваться неуправляемым кодом СОМ, а неуправляемые компоненты СОМ, в свою очередь, могут использоваться кодом .NET Framework. В этой главе описывались основные понятия и концепции взаимодействия компонентов в среде .NET Framework. Службы СОМ+ вместе с новыми возможностями масштабирования .NET Framework обеспечивают все необходимое для создания масштабируемых и надежных приложений. Впоследствии все решения будут создаваться исключительно для платформы .NET Framework, поэтому можно сказать, что взаимодействие элементов больше не понадобится.
216
Глава 12. Взаимодействие элементов языка
• Переход с Visual Basic 6.0 В прошлом разработчики Visual Basic могли после некоторой доработки перенести программный код, созданный в одной версии языка, в другую. Элементы управления VBX, используемые ранее в среде Visual Basic, были заменены элементами управления ActiveX, также произошел переход с 16-разрядной платформы на 32-разрядную, но еще никогда сделанные изменения не были столь значительны. С появлением .NET Framework разработчики получили возможность переходить не только с одной версии Visual Basic на другую, но и на разные платформы. Среда | .NET Framework выполняется на верхнем уровне Win32 и I обеспечивает широкие возможности взаимодействия. Но, несмотря на это, факт остается фактом: .NET Framework | является совершенно новой операционной средой.
Элементы Visual Basic 6.0, I измененные в VB.NET В предыдущих главах речь шла об изменениях в VB.NET. В этом разделе еще раз рассматриваются те проекты, синтаксические конструкции языка и возможности, которые изменены или удалены при переходе с Visual Basic 6.0 на VB.NET.
Типы проектов Большая часть типов проектов, существующих в Visual Basic 6.0, соответствует типам проектов Visual Basic.NET; правда, некоторые из них более недоступны. Приложения ITS, больше известные как WebClasses, были введены в Visual Basic 6.0 для упрощения процесса разработки Web-приложений ASP. Несмотря на то что сами WebClasses были удалены, некоторые из их нововведений нашли свое воплощение в .NET Framework в виде WebForms ASP.NET. WebForms, как и WebClasses, позволяют отделить графическую часть
проектирования Web-приложения от разработки программного кода, непосредственно реализующего приложение.
Приложения DHTML Эти приложения выполнялись в Internet Explorer. Концепция приложений DHTML достаточно интересна, но, к сожалению, среда проектирования и отладки отсутствуют, поэтому подобных приложений фактически не существует. В настоящее время в .NET Framework представлены две основные модели клиентского выполнения — приложения DHTML, созданные на основе языка сценариев JavaScript, и клиенты Windows-форм, совместно использующие характеристики развертывания HTML.
Документы ActiveX Документы ActiveX подобны приложениям DHTML, в которых они выполняли роль ведущего узла. Но, в отличие от этих приложений, они являются клиентами Windows, обладающими широкими возможностями. В .NET Framework документы ActiveX, как и приложения DHTML, заменены формами Windows.
Приложения ActiveX EXE Это специализированные внепроцессные (т.е. работающие не в клиентском процессе) серверные приложения. В среде .NET Framework не существует типов проекта, сопоставимых с данными. .NET Framework является многопоточной средой, которая не имеет ограничений, присущих модели поточной обработки компонентов СОМ. Поэтому потребность во внепроцессорных серверных приложениях значительно уменьшилась. Единственной функциональной возможностью, которая не обеспечивается приложениями .NET Framework, является метод активизации приложений.
Проекты данных Проекты данных использовались в первую очередь для создания приложений-отчетов. Возможности подобных проектов могут быть получены с помощью инструментальных средств данных Visual Studio.NET, типизированных наборов данных D a t a S e t и нового приложения Crystal Reports.NET.
Конструкции языка Компания Microsoft во время работы над VB.NET попыталась, насколько это возможно, очистить язык Visual Basic. Некоторые разработчики считают это решение необдуманным, а некоторые полагают, что Microsoft не стала заходить слишком далеко. Ряд удаленных ключевых слов поддерживает старые, неструктурированные конструкции программирования. Другие редко используются разработчиками. Многие ключевые слова, оставленные в предыдущей версии, более не нужны, так как .NET Framework позволяет обеспечить те же функциональные возможности в альтернативной форме. И лишь немногие из них удалены из-за несоответствия правилам .NET, относящихся к порядку работы и взаимодействия языков (табл. 13.1).
218
Глава 13. Переход с Visual Basic 6.0
Таблица 13.1. Удаленные элементы языка Неиспользуемый элемент программирования
Заменен на
Ключевая фраза As Any
Перегрузка функции Класс System.Globilization.Calendar Тип данных Decimal Метод System.Drawing.Graphics.DrawEllipse Свойство Today типа данных System. Date System.Diagnostics.Debug.Assert System.Diagnostics.Debug.Write Замены нет Метод System.Windows.Forms.Application.DoEvents
Свойство C a l e n d a r Тип данных C u r r e n c y Оператор C i r c l e Функция и оператор Date Метод D e b u g . A s s e r t Метод D e b u g . P r i n t Операторы Def t y p e Функция DoEvents Ключевое слово Empty
Ключевое слово N o t h i n g
Оператор Eqv
Оператор =
Оператор GoSub
Замены нет
Оператор Imp
Вместо A imp В используется (Not A) or В
Событие I n i t i a l i z e
Конструкторы
Свойство I n s t a n c i n g
Модификаторы доступности
Функция I s Empty
Замены нет
Функция i s M i s s i n g
Перегрузка функции Метод Microsoft.VisualBasic.Information.IsDBNull Метод Microsoft.VisualBasic. Information.IsReference Замены нет
Функция i s N u l l Функция i s O b j e c t Оператор L e t Оператор L i n e Оператор LSet Функция MsgBox
Метод System.Drawing.Graphics.DrawLine Метод System.String.PadLeft MsgBox в библиотеке совместимости и класс MessageBox в .NET Framework
Ключевое слово N u l l
Ключевое слово N o t h i n g
Конструкция On . . . GoSub
Замены нет
Конструкция On . . . GoTo
Замены нет
Оператор O p t i o n Base
Замены нет
Модификаторы доступности Оператор Option Private Module Операторы Property Get, Новая синтаксическая конструкция Property Let и Property Set Метод PSet Пространство имен S y s t e m . D r a w i n g и S y s t e m . D r a w i n g . Design
Оператор GoSub Функция Rnd Функция Round
Конструкции языка
Замены нет
Метод System.Math.Rnd Метод System.Math.Round
219
Окончание табл. 13.1 Неиспользуемый элемент программирования
Заменен на
Оператор Rset
Метод System.String.PadRight Пространство имен System. Drawing и System. Drawing. Design
Метод S c a l e Функция Sgn Функция Sqr Функция S t r i n g Событие T e r m i n a t e
Метод System.Math.Sgn Метод System.Math.Sqr Конструкция System.String Метод F i n a l i z e или интерфейс System. Idisposable
Оператор Туре
Свойство System.Date.TimeOf Day Оператор S t r u c t u r e
Тип данных V a r i a n t
Тип данных Obj e c t
Функция VarType
System.TypeCode Оператор End While
Функция Time
Ключевое слово Wend
Недокументированные возможности Достаточно часто разработчики Visual Basic используют недокументированные и неподдерживаемые функции (несмотря на многократные предупреждения). Большая часть этих функций возвращает адрес переменной. Эти функции удалены из Visual Basic.NET, но, несмотря на это, в .NET Framework была введена поддержка их функциональных возможностей. Появление дополнительных функциональных возможностей не только повлияло на обработку в .NET Framework, но в большинстве случаев значительно улучшило и новые методы.
Изменения в языке В табл. 13.2 приведены основные возможности языка, измененные в Visual Basic.NET. Таблица 13.2. Изменения в Visual Basic.NET Изменение
Описание
Операторы Date и Time
Visual Basic.NET заменил операторы Visual Basic 6.0 D a t e и Time операторами Today И TimeOf Day
Заменены методы P s e t и S c a l e
В VB.NET не существует непосредственного эквивалента этим операторам. Подобные функциональные возможности доступны в пространствах имен S y s t e m . D r a w i n g и System.Drawing.Design
Расширено свойство C a l e n d a r
Функциональные возможности, обеспечиваемые свойством C a l e n d a r , в VB.NET обрабатываются классами
System.Globalization.Calendar и System. Globalization.Culturelnfо
Заменены Empty и N u l l ; функция IsEmpty не поддерживается
220
Empty и N u l l были заменены ключевым словом N o t h i n g для проверки неинициализированных переменных и недостоверных данных
Глава 13. Переход с Visual Basic 6.0
Окончание табл. 13.2 Изменение
Описание
Функции, использующие символ $ для указания строковой версии, были заменены перегрузкой функций
В Visual Basic 6.0 функции, подобные T r i m , существуют в двух версиях: одна версия для строковых, вторая —/для
универсальных типов данных. BVB.NET применяется только одна версия, использующая перегрузку операций
Изменены графические функциональные возможности
Пространство имен S y s t e m . D r a w i n g обеспечивает функциональные возможности, ранее определяемые операторами C i r c l e и L i n e
Изменены математические функцио- Функции A t n , Sgn и Sqr были заменены классом System. нальные возможности Math, который обеспечивает более расширенные функциональные возможности Функции, определяющие значения и объекты N u l l , перемещены в класс
Microsoft.VisualBasic. Information Заменены методы Debug. P r i n t и Debug.Assert
Заменена функция VarType
Методы i s D B N u l l и i s R e f e r e n c e класса M i c r o s o f t . V i s u a l B a s i c . I n f o r m a t i o n и родственные классы обеспечивают большую часть основных задач Visual Basic Пространство имен S y s t e m . D i a g n o s t i c s предоставляет класс Debug, который, в свою очередь, обеспечивает методы W r i t e , W r i t e l f , W r i t e L i n e , W r i t e L i n e l f , Assert и Fail Функциональные возможности V a r T y p e в настоящее время обеспечиваются полем V a l u e класса S y s t e m . TypeCode
Переход от VB 6.0 к VB.NET VB.NET предоставляет инструментальные средства, позволяющие упростить преобразование программного кода Visual Basic предыдущих версий. Следует заметить, что данные средства только в очень редких случаях позволяют модернизировать приложение полностью. Если говорить в общем, то приложения, созданные в соответствии с принципами Windows DNA, имеют гораздо большую вероятность успешной модернизации. В процессе миграции некоторые типы приложений могут быть изменены. •
ActiveX DLL. Приложения этого типа могут быть преобразованы достаточно успешно, так как обычно состоят главным образом из бизнес-логики.
•
Standard EXE. Приложения, созданные на основе связного доступа к данным, имеют наименьшие шансы.
•
ActiveX EXE. Если приложения были созданы в целях автоматизации, их лучше оставить в Visual Basic 6.0.
• Приложения для IIS. Приложения этого типа могут быть изменены лишь частично. Средство преобразования создает новое приложение, оставляя приложение, созданное в Visual Basic 6.0, без изменений. В большинстве случаев используется свойство межъязыкового взаимодействия модели СОМ, позволяющее многократно применять существующие компоненты СОМ вместо их преобразования. Так, например, приложение, содержащее ссылки на объекты ADO, не будет автоматически преобразовано в приложение, использующее объекты ADO.NET. (Но вам, конечно, ничто не помешает после миграции приложения выполнить необходимые преобразования вручную.)
Переход от VB 6.0 к VB.NET
221
После завершения миграционного процесса создается отчет в формате DHTML, в котором описываются проблемы, обнаруженные в данном приложении. Кроме этого, описание обнаруженных проблем вводится в источник в виде комментариев ToDo, которые отображаются в окне задач Visual Studio.NET.
Схема миграционного процесса Миграционный процесс выполняется в виде шагов мастера, определяющих ключевые параметры преобразования. В качестве иллюстрации воспользуемся приложением Visual Basic версии 6.0, которое находится на компакт-диске Visual Basic.NET Resource CD. Для вызова мастера достаточно всего лишь открыть какой-либо проект, созданный в Visual Basic 6.0, в диалоговом окне Open Project, После того как вы откроете проект, мастер Visual Basic Upgrade Wizard начнет свою работу. Начальный экран мастера показан на рис. 13.1. Этот экран представляет собой просто начало работы мастера миграции и каких-либо функциональных возможностей не обеспечивает.
welcome to the visual Basic Upgrade Wizard You are attempting to open л visual Basic 6.0 project thai must be upgraded to Visual Basic.NET befoie r! can be opened.
• Oeate a new project to which your project will be upgraded • Copy form and class files to the new protect and convert them to the new format. • Create an upgrade report and add it to your new project.
Рис. 13.1. Начальное диалоговое окно мастера Visual Basic Upgrade Wizard
На рис. 13.2 показано диалоговое окно мастера, позволяющее выбрать параметры модификации, доступные для приложений Windows. Кроме этого, можно указать способ поддержки существующих массивов, а также генерировать заданные по умолчанию интерфейсы объявленных классов. Заданные по умолчанию интерфейсы потребуются в том случае, если указанные компоненты все еще применяются с помощью клиентов СОМ, использующих автоматизацию. Диалоговое окно, показанное на рис. 13.3, позволяет определить место хранения измененного приложения. На рис. 13.4 показано окно, предшествующее началу процесса миграции. На рис. 13.5 иллюстрируется процесс преобразования проекта. После того как процесс миграции проекта будет завершен, в окне мастера появится отчет, содержащий информацию, относящуюся к данному проекту, а также описание проблем, выявленных при преобразовании проекта (рис. 13.6). Команда разработчиков VB.NET пришла к решению, что отчет должен содержать в себе не только ссылки на справочную систему Visual Studio.NET, но и ссылки на узлы Internet, позволяющие получить более подробную информацию.
222
Глава 13. Переход с Visual Basic 6.0
Visual Basic Upgrade Wizard - Page 2 of 5 Choose a Project Type and Set Options The wizard can tpgtade youi project to one of sevetal new project types and can perform optional upgrade actions. Your Visual Basic Б.0 project is г Windows Application. What Ijpe of protect would you fee *w to be traded to? & EXE С DLL l зийот con!to! lib-ад Ale lh«e additional actions you wart the w a d to perfaan?
Рис. 13.2. Диалоговое окно Choose a Project Type and Set Options Visual Basic Upgrade Wizard - Page 3 of 5 Specify в Location for Your New Project The wizard v4 place your new project files in a new raider Wheie do you want youi new project (seabed? |FAVBDdNelF«Develope!sSVBSConveision The project will be created as: F:WBDolNetFaDevelopersW66Convefsbn4VB6GoodE«atrple.vbpiO(
Л1С. 7J.J. Диалоговое окно Specify a Location for Your New Project Visual Basic Upgrade Wizard • Pa^ 4 of 5 Ready to Upgrade The waaid has now enough information to upgtade you pfojecttoVisualStudio.NET. This may take a lew minutes, ot several hours, depending on the size of your project
Click Next to begin the upgrade
Puc. 13.4. Диалоговое окно Ready to Upgrade Переход от V B 6 . 0 K V B . N E T
Cancel
Nexl>
223
Please wait... The tystm is upgradn i g you proe j ct to Visual Batc i .NET. Statui: Parsn i g [m i GoodExampWrm., •II Estimated time left 3 мгнЛф)
Рис. 13.5. Процесс преобразования запущен 3
vnfiGooriFxii
Fie Edt Ve iw Favorites Toos l Hep l
•ыa
•df FevorKes
PersonalBar
| Address j
UftofProe jctFilet —
ц
£
)
(
O
l
•
3
н
f
-
J
f
r
U
c
b
*
g
l
t
l
o
u
M
p
v
R
:
R
E
w
t
i
a
t
e
*
e
I
r
i
t
r
S
i
l
m
*
t
l
m
a
n
t
l
m
n
t
i
m
u
u
n
r
t
t
l
i
f
t
v
p
J
l
U
e
I
t
_
.
v
f
S
u
_
.
m
m
_
W
o
f
r
t
V
m
Q
o
s
d
t
H
r
n
i
n
g
o
T
I
c
i
o
a
n
t
N
i
n
t
T
h
r
a
*
W
a
r
n
i
n
g
T
I
p
W
a
r
n
i
n
g
T
i
p
n
i
n
g
n
i
n
g
T
•
T
.
n
e
r
a
I
g
r
l
p
I
n
a
o
N
i
i
p
'
f
a
t
T
T
v
*
_
3
N
n
a
m
_
m
p
r
W
i
_
r
p
a
W
T
a
W
*
«
a
_
b
L
t
n
u
s
y
n
u
n
Т.Ы1»ш
WMl4>
)
'
i
u
R
3
u
d
u
R
F
d
d
e
R
*
o
a
S
.
3
6
a
'
r
•
\
*
O
1
2
b
*
m
p
•
r
)
о
Em.
•
f
n
_
e
t
'
d
V
E
m
H
"
,
*
_
m
"
p
£
l
a
.
2
Z
f
r
m
T
y
p
.,
,
F
'
Z
L
o
r
m
H
a
I
I
I
!
"
I
'
p
g
r
a
4
«
d
w
-
i
t
h
i
f
Z
i
I
u
a
6
i
!
G
b
J
4
C
t
i
O
b
j
a
c
t
m
a
P
r
t
p
a
n
y
P
i
U
N
u
l
*
U
f
c
s
•
£
A
r
i
d
r
p
.
F
i
r
m
n
C
I
n
t
C
I
n
t
I
U
N
p
o
t
)
n
u
p
J
g
<
d
r
a
i
r
t
l
o
n
•
i
j
l
l
t
'
t
r
t
-
t
v
U
s
t
i
e
t
«
f
-
r
e
f
i
t
r
t
v
o
f
a
h
l
a
e
i
j
.
U
*
o
0
H
U
: . : : . : • ! '
:•'
?
J >
fj
l.S
1 4 .
1
f
t
d
i
0
wrttl
tiwuhUehaettft
Upgrade Settings Gtfteratel Lo<|filci V
-
•
;
'
•
•
'
•
•
"
'
J
"
~
—
i
f
с. /J.6. Отчет мастера Visual Basic Upgrade Wizard 224
Глава 13. Переход с Visual Basic 6.0
На рис. 13.7 показано приложение, находящееся в окне Visual Studio.NET вместе со списком задач и приведенным отчетом процесса миграции. Двойной щелчок на какомлибо из элементов списка задач приведет непосредственно к проблеме, описанной в списке задач. Кроме этого, код проекта содержит комментарии, характеризующие возникшие проблемы, а также ссылки, обеспечивающие доступ к подробной информации, которая может помочь в решении этих проблем. E*
E*
У-
Е"*с
В*
C*u,
IM
jfrd.
•• '- K', i •-• • r- • «P« Г4 » « • X :Ц< Solution U * в
S J L O A N
£
SiJRe
T y p e not d s ( n B d A x M 5 H i « a i c h i c « I F I e i i G t k « . b A « M C : \ O o c u r n e n U a n d . ..VfimG rid.
Тура not defined A ^ S H i m c h i u t ^ r i d L b A i M СЛОоситепи and ...yimGiid. The name tipboatd1 is not declared C;\Documentsand..,V[rniGrid The name "Clipboard1 is not declared. C:^Documents and ,..4/imGiid vl The name Dipboaro" is not declared. C:\Documenlsand ...VirmGird.vt
Puc. 13.7. Преобразованный проект VBe VisualStudio.NET
Анализ миграционного процесса Миграция приводит к существенному увеличению объема работы, поэтому к перемещению существующих приложений в .NET Framework следует относиться взвешенно и преобразовывать только те из них, которые должны быть перенесены на новую платформу. Определить, какое из приложений следует переместить в .NET Framework, довольно сложно. При этом придется учесть множество различных факторов, например необходимость использования приложений или компонентов из .NET Framework или сложности миграции данного приложения. Приложения, созданные в Visual Basic 6.0, будут поддерживаться еще в течение нескольких лет. Поэтому, если необходимо расширить приложение до каких-либо пределов, у вас осталось еще достаточно времени для того, чтобы оценить целесообразность его миграции в .NET Framework. Обратите внимание, что далеко не все типы приложений подходят для .NET Framework. Например, приложения, использующие объекты DAO или RDO, переместить без дополнительных изменений будет достаточно сложно. Приложениям Windows потребуются наиболее радикальные изменения, поэтому отберите для миграции только компоненты бизнес-уровня, а для перемещения пользовательского интерфейса воспользуйтесь свойством межъязыкового взаимодействия.
Создание нового приложения Visual Basic 6.0 Маловероятно, что вы отложите все новые разработки до того времени, когда VB.NET будет принят в вашей организации. Но определенные методы могут быть приняты на вооружение уже сейчас, что позволит в будущем существенно упростить процесс миграции.
Создание нового приложения Visual Basic 6.0
225
Используйте стандартные документы Во многих организациях признаком хорошего тона является использование стандартов и основных руководящих принципов программирования. Поэтому, если вы намерены когда-либо переходить к VB.NET, постарайтесь создавать, опубликовывать и вводить в действие стандарты, несмотря на то что в вашем лице может быть представлен весь вычислительный центр. Одним словом, делайте так, чтобы новый разработчик смог достаточно быстро разобраться в вашем проекте. Использование стандартных документов позволяет программировать для "того парня". Также это поможет сохранить совместимость кода при его передаче из отдела в отдел.
Обучение Еще никогда обновление Visual Basic не было столь всесторонним. Из этого следует, что именно сейчас обучение приобрело особую важность. Вы не сможете так просто взяться за VB.NET и сразу же воспользоваться его многочисленными преимуществами. Для этого придется заново обдумать, как лучше выполнить ту или иную операцию. Среда .NET Framework содержит более 6500 оптимизированных библиотек классов. Зачем же снова изобретать велосипед, если в библиотеках вы сможете найти самые различные функциональные возможности, обеспечиваемые тем или иным классом.
Явное объявление Предыдущие версии Visual Basic были чрезвычайно "терпимы" к пользовательским ошибкам. Это свойство перешло в Visual Basic.NET, по крайней мере по умолчанию, поэтому основным требованием к программному коду, перемещаемому из Visual Basic 6.0 в VB.NET, должно быть явное объявление. • Используйте Option E x p l i c i t в каждом модуле. Это гарантирует, что все переменные будут объявлены. • "Строго" определяйте тип всех переменных. Средство миграции позволяет легко преобразовывать строгие типы в новые эквивалентные типы .NET Framework. • Явно конвертируйте все переменные. Не полагайтесь на автоматическое приведение типа. • Явно объявляйте все переменные. Наиболее распространенная проблема в приложениях VB и ASP состоит в создании переменных, используемых только в i данном коде. Установите во всех проектах параметры Option E x p l i c i t On и Option S t r i c t On. • He используйте свойства, заданные по умолчанию. В VB.NET большая часть заданных по умолчанию свойств исчезла, так как заданные по умолчанию свойства должны иметь параметр. •
Используйте константы вместо буквенных значений.
• Правильно определяйте тип переменных. В Visual Basic 6.0 некоторые типы данных могут использоваться для различных целей. Например, Date может быть использован как Double, а логические значения могут быть сохранены как целые числа. В большинстве случаев VB.NET не поддерживает подобного использования.
226
Глава 13. Переход с Visual Basic 6.0
План изменений Многочисленные изменения VB.NET требуют от программиста совершенно иного подхода. К счастью, большая часть необходимых операций может быть выполнена в Visual Basic 6.0. Поэтому обратите внимание на те основные требования, которые позволяют существенно упростить переход к VB.NET. • Используйте "нулевые" массивы. Встроенные массивы VB.NET должны начинаться с нулевого элемента. Существует метод .NET Framework, позволяющий использовать "ненулевые" массивы, код которого является слишком громоздким и более медленным. •
Постарайтесь не зависеть от выполнения обоих условий логической операции. Эти операции VB.NET теперь сокращаются.
•
Избегайте использования измененных или удаленных элементов языка. Держите перечень указанных элементов под рукой, можете даже придать ему статус официального документа.
Использование XML Для передачи данных на различные уровни приложений используйте язык XML. Использование XML позволяет не только повысить взаимодействие и гибкость уровней приложений СОМ, но и значительно упрощает взаимодействие СОМ-приложений и приложений .NET Framework. Можно использовать XML в виде данных, передаваемых на нижний или верхний уровни приложения, или же пойти немного дальше и воспользоваться инструментальными средствами Microsoft SOAP, что позволит применять SOAP в качестве протокола вызова Web-служб ASP.NET из приложений СОМ или наоборот, как показано в листинге 13.1. Листинг 13.1. Вызов Web-службы в Visual Basic 6.0 Const WSDL = "http://localhost/HelloWorldWebService/HelloWorld.asmx?WSDL" Dim oHelloWocldWebService as SoapClient Dim sHelloWorld as String Set oHelloWorldWebService = New SoapClient oHelloWorldWebService.MSSoapInit WSDL sHelloWorld = OHelloWorldWebService.HelloWorld
Резюме Миграция приложений и компонентов из Visual Basic 6.0 в VB.NET не сводится к повторному компилированию. Обратите внимание, что при этом происходит не только изменение объектной модели, но также изменяется и используемая платформа. Это обычно значительно увеличивает объем требуемой работы. Поэтому во многих ситуациях более разумно будет оставить существующие приложения в Visual Basic 6.0, расширив их для взаимодействия с VB.NET и .NET Framework. Компания Microsoft приложила немало усилий для того, чтобы сохранить целостность существующих приложений Visual Basic 6.0 при инсталляции новых приложений VB.NET на ту же систему. Вы, как разработчик, решаете сами, в каких случаях можно рекомендовать администрации или заказчику оставить то или иное приложение в Visual Basic 6.0, а когда следует переместить его в VB.NET или преобразовать его архитектуру для .NET Резюме
227
Framework. В том случае, если у вас нет определенных планов, связанных с расширением функциональных возможностей приложения, лучше оставить его без изменений. Среда .NET Framework содержит множество различных средств, которые достойны перемещения приложений или полного преобразования их архитектуры. В этой ситуации вы возлагаете на себя всю ответственность за принятое решение, которое может принести определенную пользу как отдельному приложению, так и всей организации.
228
Глава 13. Переход с Visual Basic 6.0
Будущее .NET Framework Итак, что могут ожидать разработчики в отношении .NET Framework в будущем?
Кроссплатформенность .NET Framework Компания Microsoft представила некоторую часть библиотеки классов .NET Framework, спецификации служб и язык С# на рассмотрение в Европейскую ассоциацию производителей компьютеров, надеясь на их использование в качестве стандартов. Если эта попытка окажется успешной, многие из поставщиков смогут реализовать .NET Framework на других платформах. Обратите внимание, что на рассмотрение было представлено только подмножество библиотеки классов. Теперь формирование подмножества классов, поддерживающих кроссплатформенные возможности, зависит только от усилий разработчиков. Честно говоря, пока кто-либо или сама Microsoft не добавят дополнительных классов оболочки, кроссплатформенная реализация не сможет получить широкого применения.
Дополнительные Web-службы Одной из новинок Microsoft, с которой вы, вероятно, встретитесь, являются дополнительные Webслужбы. Первой и, следует заметить, далеко не последней реализацией Web-службы от Microsoft является Hailstorm. В скором будущем вы увидите несколько версий Web-служб, реализованных в виде отдельных элементов новых версий программных продуктов.
pH даИ
Краткий обзор Hailstorm Компания Microsoft представляет сервисы, выполняющие роль "сервисов стандартного блока", которым присвоено имя Hailstorm. Они обеспечивают целый ряд Web-служб, созданных на основе .NET Framework. Web-службы, входящие в состав Hailstorm, объединены с Microsoft Passport и Microsoft Instant Messenger. Microsoft Passport является системой пользовательской аутентификации, используемой в настоящее время. Теперь пользователь может зарегистрироваться только в одном месте, одновременно получая доступ к нескольким Web-узлам. Сейчас происходит расширение Microsoft Passport, что позволит в дальнейшем обращаться к дополнительным Web-службам и хранить большой объем пользовательской регистрационной информации. Операционная система Microsoft Windows XP поддерживает возможность непосредственной регистрации пользователя в Microsoft Passpoit во время начала работы на компьютере. Microsoft Instant Messenger (MIM) является в настоящее время широко используемой службой мгновенной передачи сообщений, которая позволяет людям общаться друг с другом в режиме реального времени. Сегодня у вас появилась возможность пересылать документы адресатам, звонить по телефону или организовывать собрания в сети с помощью MIM, не считая уже привычной возможности передачи текстовых сообщений. MIM, как Microsoft Passport, также расширяется, так что теперь приложения могут отправлять сообщения пользователям с помощью SOAP и Web-служб. Ядро Hailstorm содержит большой объем информации, относящейся к пользователю, а также права, необходимые для получения доступа к указанным данным. Благодаря этой информации, доступ к которой может быть получен с помощью Web-служб, электронные бизнес-приложения смогут значительно расширить функциональные возможности. В качестве использования Hailstorm и Web-служб рассмотрим пример с путешествием. Пользователь обращается на соответствующий Web-узел, например Microsoft Ехреdia. Поскольку пользователь, входя в систему, регистрируется в Microsoft Passport, Expedia автоматически получает доступ к пользовательской информации, находящейся в Hailstorm. На основе полученных данных Expedia определяет исходный пункт путешествия, предполагаемый маршрут следования, тип арендуемого автомобиля и т.п. Когда пользователь соглашается с предлагаемыми условиями, Expedia использует ту форму оплаты, которая была определена пользователем в Hailstorm. Подобная система значительно упрощает обслуживание. Но Hailstorm на этом не останавливается. Известно, что после оформления заказа очень многое может измениться. Expedia или какие-либо другие службы, участвующие в обработке пользовательской информации, уже знают предполагаемый маршрут и время путешествия и поэтому могуг предоставить пользователю дополнительные услуги. Например, авиакомпания, самолетом которой собирается лететь пользователь, может использовать его контактные данные для передачи мгновенных сообщений или сообщений электронной почты в случае отмены рейса или изменения времени вылета. Теперь вам не придется целый день "сидеть на телефоне" и надоедать диспетчеру своими вопросами. Вся необходимая информация будет получена в виде мгновенных сообщений или сообщений электронной почты, отправленных через Hailstorm на все возможные пользовательские устройства (сотовый телефон, персональный или "карманный" компьютер и т.п.). В табл. 14.1 приведен набор служб, первоначально включенных в Hailstorm. Таблица 14.1. Службы Hailstorm (из Microsoft Hailstorm Documentation) Служба myAddress
230
Назначение Электронный и географический адрес, используемые для идентификации
Глава 14. Будущее .NET Framework
Окончание табл. 14.1 Служба myProfile myContacts myLocation myNotif i c a t i o n s my I n b o x
Назначение Имя, псевдоним, особые даты, фотография Электронная адресная книга Электронное и географическое местоположение и место встречи Подписка на уведомления, управление и маршрутизация Элементы почтового ящика, такие, как электронная или голосовая почта, в том числе и существующие почтовые системы
myCalendar
Управление временем и задачами
myDocuments
Хранение незавершенных документов
m y A p p l i c a t i o n S e t t i n g s Настройки приложения myFavoriteWebSites myWallet
Избранные адреса URL и другие Web-идентификаторы Квитанции, средства оплаты, купоны и другие финансовые записи
my D e v i c e s
Параметры и свойства устройств
myServices
Службы, обеспечивающие идентичность
myUsage
Отчет об использовании предыдущих служб
Hailstorm в скором будущем станет основным набором служб, которые будут восприниматься большинством пользователей как что-то само собой разумеющееся. Несмотря на это, Hailstorm позволит значительно упростить использование приложений для Internet следующего поколения. Службы, вошедшие в Hailstorm, созданы на основе SOAP, поэтому они будут доступны для любого пользователя, независимо от используемой платформы или устройства. Разработчики, использующие Visual Studio.NET и, в частности, VB.NET, будут находиться в самом центре Hailstorm.
Интеграция .NET Framework и .NET Enterprise Servers В настоящее время .NET Framework предоставляет классы, позволяющие использовать службы С0М+, системные службы (например, служба регистрации событий), а также средств мониторинга, MSMQ и SQL Server 2000. Для того чтобы воспользоваться другими службами, разработчики должны использовать средство межъязыкового взаимодействия COM Interop. Ожидается, что в скором будущем Microsoft расширит прямую поддержку серверов предприятий. В некоторых случаях CLR будет интегрирована непосредственно в программный продукт. Например, в июле 2000 года в Орландо (Orlando), шт. Флорида, компания Microsoft организовала предварительный показ очередной версии SQL Server с кодовым именем Yukon. Эта версия позволяет разработчикам создавать хранимые процедуры на любом из .NET-языков, а также сохранять объекты, непосредственно сгенерированные с помощью .NET Framework, в таблицах базы данных SQL Server. Реализация этой версии позволит фантастически расширить возможности SQL Server. В 2002 году предполагается полная интеграция .NET Framework в операционную систему. А вот что из этого получится — время покажет.
Интеграция .NET Framework и .NET Enterprise Servers
231
Резюме Вы, как разработчик Visual Basic, получаете инструмент, который позволяет разрабатывать следующие поколения приложений для Internet. Вам, наверное, не один раз приходилось выслушивать доводы разработчиков, отвергающих предыдущие версии Visual Basic по причинам, которые в настоящее время не имеют под собой никаких оснований. Сейчас все зависит только от вас, вашего умения и знания основ .NET Framework. Сейчас только вы сможете убедиться в том, что Visual Basic никогда не станет языком второго класса. Возможности для этого есть; вам остается только ими воспользоваться.
232
Глава 14. Будущее .NET Framework
•
Приложение Windows Form В этом приложении описывается процесс создания примера приложения Windows Form, использующегося на промежуточном уровне Web-службы ASP.NET Создание Web-службы приведено в приложении Б, "Webслужба ASP.NET и приложения Web Forms". Средним уровнем называется промежуточный логический уровень между Web-клиентом и базой данных. Компоненты .NET Framework, используемые в данном проекте, показаны на рис. А. 1. C#
Visual Basic
J Г~ JScript
C++
Языки сторонних разработчиков
Спецификация единого языка Основные компоненты среды исполнения .NET Оболочка
Internet Explorer
Элементы управления
Базовые классы .NET Framework AOO.NET ) (
XML
) (
Сеть
) (Ввод-вывод
Службы
Единая среда исполнения
(Управлениепамятью)
(
Сборкамусора
)
(
) С 'ГпУнЕиГ ) I
Рис. АЛ. Компоненты .NET Framework, используемые в процессе создания приложения Windows Form
Обработка данных спортивной статистики Это приложение предназначено для сбора и обработки статистических данных, касающихся бейсбола. Диаграмма отношений между таблицами базы данных SQL Server 2000 приведена на рис. А.2. На рис. А.З— А.7 показаны формы, которые будут созданы для данного приложения. >. SupcrStotsEnlry - Mtoosoft Visual BssicNtT MraHj»] - dboJJasebaistaeisttc» »B Eite
l&
gew
Protect
i P - J - C S y S
BuM
Cebug
Diagram,
tools
ЩИ*"
Щ> | s u p e r 5 t a t ! i r t ^ - Microsoft Visual Basic.NI
»• ' - Q, ' • Debug v.S < й ! 100%
vb Trestodts.vb dbo.Ba.tbaUStd..BallSlatWlc.)*| < •x "o
r.vb [Desg i n] tUTeams • ]
FKJWPKchersJWTeams tbPitchng£t30sOcs " ] Pa l yer " Team FK_tbT l eafnFa i yersJbT l aarns ; i-C-attng-taosocs _£|!С
П
Player
5 ИауегШ
tbPlayers
Рис. А.2. Диаграмма базы данных SQL Server 2000
234
Приложение А. Приложение Windows Form
* Мд,пг League B a i a b i A Statistic* Year чепсап League Chicago White Sox \ Magglio Ordone E Frank Thomas
J Ga...
I At Bats
I RBIs
582 .
8 Jim Parque !• Pitching Batting \ Baltimore Orioles 1 Minnesota Twins National League Й Cincinnati Reds i ; Ken Griffey Jr. i Chicago Cubs Players [ Ken Griffey Jr. j Jim Parque Magglio Ordonez Frank Thomas
Puc. A3. Главная форма :MAdd or Update I Chc i ago While So» r
HaUonal League
^ Amencan League
.Cancel
Рис. А.4. Форма Add or Update Team
Рис. А.5. Форма Add or Update Player
I • ftdd ш update Betting Statistics Н Я Ш Ц Е Э 1 : Ye,,
й
I " 1
1
OK ;
Games
I
мы,
I582
;
1 Home Runs I ^ : RBI'. ll«
i
1
Cancel
Рис. Л. 6. Форма Add or Update Batting Statistics Puc. A. 7. Форма Add or Update Pitching Statistics
Источник данных приложения Передача данных в создаваемом приложении осуществляется с помощью тщательно разработанного типизированного набора данных. В набор данных D a t a S e t входят таблицы, показанные на рис. А.6. Предлагаемый метод не идеален и не может служить образцом для разработки приложений, но позволяет понять основные принципы разработки. На рис. А.6 показана схема XSD, которая описывает набор данных D a t a S e t .
Ill L
• string iString
j
И'
Е Team Е Vear
— •
string
И
:mt
Лге. Л6. Набор данных TeamsAndPlayers
Загрузка дерева После получения набора данных D a t a S e t из среднего уровня приложения определенная часть данных будет загружена в элемент управления System.Windows. Forms . T r e e v i e w ( T r e e v i e w ) . Код, используемый для загрузки, приведен в листинге АЛ. Этот код иллюстрирует ряд методов, используемых разработчиками для работы с наборами данных DataSet и управляющими элементами Treeview. Для повышения эффективности итерации табличных данных DataSet в этом коде используются типизированные наборы DataRow.
236
Приложение А. Приложение Windows Form
Листинг А.1. Загрузка данных в элемент управления Treeviev Private Sub LoadTreeView() Dim oNode As PlayerNode Dim oNodePlayers As TreeNode Dim oNodeAmericanLeagueTeam As TreeNode Dim oNodeNationalLeagueTeam As TreeNode Dim oNodeTeam As TeamNode Dim oNodeTeamPlayers As TeamPlayersNode Dim oNodePlayer As PlayerNode Dim oNodePitching As PitchingNode Dim oNodeBatting As BattingNode Dim oTeamRow As TeamsAndPlayers.TeamsRow Dim oTeamPlayers As TeamsAndPlayers.TeamPlayersRow Dim oPIayerRow As TeamsAndPlayers.PlayersRow Dim oPitchingRow As TeamsAndPlayers.PitchingStatisticsRow Dim oBattingRow As TeamsAndPlayers.BattingStatisticsRow Dim bFound As Boolean treeTeamsAndPlayers().Nodes.Clear() ONodeAmericanLeagueTeam = treeTeamsAndPlayers(). 4>Nodes.Add("American League") ONodeNationalLeagueTeam = treeTeamsAndPlayers(). 4>Nodes.Add("National League") oNodePlayers = treeTeamsAndPlayers().Nodes.Add("Players") For Each oTeamRow In c_oTeamsAndPlayers.Teams.Rows oNodeTeam = New TeamNode(oTeamRow.ID, oTeamRow.TeamName) If oTeamRow.League = "AL" Then oNodeAmericanLeagueTeam.ForeColor = System.Drawing.Color.Red oNodeAmericanLeagueTeam.Nodes.Add(oNodeTeam) Else oNodeNationalLeagueTeam.ForeColor = System.Drawing.Color.Blue oNodeNationalLeagueTeam.Nodes.Add(oNodeTeam) End If For Each oTeamPlayers In oTeamRow.GetTeamPlayersRows For Each oPIayerRow In c_oTeamsAndPlayers.Players.Rows If oPIayerRow.ID.Equals(oTeamPlayers.PlayerlD) Then oNodePlayer = New PlayerNode(oPIayerRow.ID, oPIayerRow.FirstName & " " & oPIayerRow.LastName) oNodeTeam.Nodes.Add(oNodePlayer). If oPIayerRow.GetPitchingStatisticsRows.Length > 0 Then oNodePitching = New PitchingNode(oPIayerRow.ID) oNodePitching.Text = "Pitching" oNodePlayer.Nodes.Add(oNodePitching) End If If oPIayerRow.GetBattingStatisticsRows.Length > 0 Then oNodeBatting = New BattingNode(oPIayerRow.ID) oNodeBatting.Text = "Batting" oNodePlayer.Nodes.Add(oNodeBatting) End If End If Next Next Next For Each oPIayerRow In c_oTeamsAndPlayers.Players bFound = False Обработка данных спортивной статистики
237
For Each oNode In oNodePlayers.Nodes If oNode.PlayerlD.Equals(oPlayerRow.ID) Then bFound = True Exit For End If Next If Not bFound Then oNodePlayer = New PlayerNode(oPlayerRow.ID, oPlayerRow.FirstName & " " & oPlayerRow.LastName) oNodePlayers.Nodes.Add(oNodePlayer) End If Next mnuNewTeam().Enabled = True mnuNewPlayer().Enabled = True mnuSave().Enabled = True End Sub Приведенный код иллюстрирует также один из способов использования наследования в приложениях Windows Forms. Обратите внимание, что в этом приложении определены шесть различных типов узлов дерева: TreeNode, PlayerNode, TeamNode, TeamPlayersNode, PitchingNode и BattingNode. Все перечисленные узлы (за исключением TreeNode) наследуются от System. Windows. Forms. TreeNode (TreeNode). Программный код пяти узлов, образованных из класса TreeNode, приведен в листинге А.2.
Листинг А.2. Использование наследования для создания Node'Xtype Imports System.Windows.Forms Public Class TeamNode Inherits TreeNode Private c_oTeamId As System.Guid Public Overloads Sub New(ByVal teamID As System.Guid) c_oTeamId = teamID End Sub Public Overloads Sub New(ByVal teamID As System.Guid, ByVal teamName As String) c_oTeamId = teamID Me.Text = teamName End Sub Public Readonly Property TeamID() As System.Guid Get Return c_oTeamId End Get End Property End Class Public Class TeamPlayersNode Private c_iTeamPlayerID As Integer Public Sub New(ByVal teamPlayerld As Integer) c_iTeamPlayerID = teamPlayerld End Sub Public Readonly Property TeamPlayerlD() As Integer Get Return c_iTeamPlayerID End Get End Property End Class Public Class PlayerNode Inherits TreeNode 238
Приложение А. Приложение Windows Form
Private c_oPlayerID As System.Guid Public Overloads Sub New(ByVal playerlD As System.Guid) c_oPlayerID = playerlD End Sub Public Overloads Sub New(ByVal playerlD As System.Guid, ByVal playerName As String) c_oPlayerID = playerlD Me.Text = playerName End Sub Public Readonly Property PlayerlD () As System. Guid .: Get Return c_oPlayerID End Get End Property End Class Public Class PitchingNode Inherits TreeNode Private c_oPitchingStatisticsID As System.Guid Public Sub New(ByVal pitchingStatisticsID As System.Guid) c_oPitchingStatisticsID = pitchingStatisticsID End Sub Public Readonly Property PitchingStatisticsID() As System.Guid Get Return c_oPitchingStatisticsID End Get End Property End Class Public Class BattingNode Inherits TreeNode Private c_oBattingStatisticsID As System.Guid Public Sub New(ByVal battingStatisticsID As System.Guid) c_oBattingStatisticsID = battingStatisticsID End Sub Public Readonly Property BattingStatisticsID() As System.Guid Get Return c_oBattingStatisticsID End Get End Property End Class
Меню Редактор меню, используемый в Visual Basic 6.0 (см. главу 9, "Обработка ошибок"), достаточно архаичен. В следующем примере приводится стандартное, хорошо знакомое меню, а также ряд всплывающих или контекстных меню. Всплывающие меню используются в узлах Treeview и L i s t v i e w . Существует два метода динамического создания всплывающего меню, вызов которых происходит автоматически при щелчке правой кнопкой мыши на элементе управления. Для создания всплывающего меню необходимо соответствующему элементу управления назначить свойство ContextMenu. Код, используемый для определения этого свойства в конструкторе форм, приведен в листинге А.З. Свойство ContextMenu устанавливается в экземпляре класса System. Windows . Forms.ContextMenu. Листинг А.З. Создание контекстного меню с oTreeViewContextMenu() = New ContextMenu() treeTeamsAndPlayers().ContextMenu = c_oTreeViewContextMenu() Обработка данных спортивной статистики
239
c_oListViewContextMenu() = New ContextMenu() lvwStatistics().ContextMenu = c_oListViewContextMenu()
В листинге А.4 приведен код обработчиков событий, относящихся к событию PopUp объекта ContextMenu. Этот код динамически генерирует и с помощью оператора AddressOf создает делегатов обработчика событий меню. Листинг А.4. Обработка события Рориробъекта ContextMenu Private Sub TreeViewPopupHandler(ByVal sender As Object, ByVal e As System.EventArgs) Handles c_oTreeViewContextMenu.Popup Dim oMenuItemChangePlayer As Menultem Dim oMenuItemChangeTeam As Menultem Dim oMenuItemAddBatting As Menultem Dim oMenuItemAddPitching As Menultem Select Case c_oClickedNode.GetType.ToString Case GetType(TeamNode).ToString OMenuItemChangeTeam = New Menultem("Update Team", _ AddressOf UpdateTeamMenuSelected) With c_oTreeViewContextMenu().Menultems .Clear() .Add(oMenuItemChangeTeam) End With Case GetType(PlayerNode).ToString oMenuItemChangePlayer = New Menultem("Update Player", AddressOf UpdatePlayerMenuSelected) oMenuItemAddBatting = New Menultem("Add Batting Statistics", AddressOf AddPlayerBattingStatistics) oMenuItemAddPitching = New Menultem("Add Pitching Statistics", AddressOf AddPlayerPitchingStatistics) With c_oTreeViewContextMenu().Menultems .Clear() .Add(oMenuItemChangePlayer) .Add(oMenuItemAddBatting) .Add(oMenuItemAddPitching) End With End Select End Sub
Создание новых записей Одна из новых интересных возможностей наборов данных DatiaSet состоит в способности создания новых записей DataRow, которые, не будучи связанными с DataSet, заполняют поля, а затем добавляют запись DataRow к таблице D a t a T a b l e . Это свойство применяется для передачи данных в диалоговые окна, используемые в приложении. В листинге А.5 в качестве примера приведен код, используемый для создания нового игрока и передачи записи DataRow как части конструктора в диалоговое окно. ЛИСТИНГ А.5. Добавление нового игрока
Private Sub mnuNewPlayer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuNewPlayer.Click Dim oPIayerRow As TeamsAndPlayers.PlayersRow Dim oNewPlayer As AddUpdatePlayer Dim oTeamPlayerRow As TeamsAndPlayers.TeamPlayersRow
240
Приложение А. Приложение Windows Form
oPIayerRow = c_oTeamsAndPlayers.Players.NewPlayersRow() oNewPlayer = New AddUpdatePlayer(oPIayerRow, c_oTeamsAndPlayers.Teams) oNewPlayer.ShowDialog(Me) If Not oPIayerRow.IsNull(0) Then c_oTeamsAndPlayers.Players.AddPlayersRow(oPIayerRow) If oNewPlayer.TeamlD.ToString.Length > 0 Then oTeamPlayerRow = c_oTeamsAndPlayers.TeamPlayers.NewTeamPlayersRow() oTeamPlayerRow.ID = System.Guid.NewGuid oTeamPlayerRow.TeamID = oNewPlayer.TeamID oTeamPlayerRow.PlayerlD = oPIayerRow.ID c_oTeamsAndPlayers.TeamPlayers.AddTeamPlayersRow(oTeamPlayerRow) End If Call LoadTreeView() End If End Sub
Визуальное наследование Для наглядной демонстрации визуального наследования создана основная форма для сбора статистических сведений по игрокам. После создания класса основной формы созданы две дочерние формы, наследованные из этого класса: A d d U p d a t e P i t c h i n g S t a t i s t i c s и A d d U p d a t e B a t t i n g S t a t i s t i c s . Форма родительского класса показана на рис. А.7. На рис. А.8 и А.9 показаны дочерние формы, полученные из формы родительского класса. SuperStatsEntry - Microsoft Visual Basc lNET [design] - ftddUpdateStattsttcs.Yti
(ite
E*
Bew
ErojMt
&Л
Q £ Ц 0 ! kT Т..Г» - K*.|
&*»*}
F»™*
•
•
;
•
•
•
:
'
:
:
-
:
,
Sffindow
Цф
- i ^ LoidBattingStaBs
м v- i. i . eEdl5,.sUci.vb[b«sign? Mart «nBaseSdaal a • Yeai Games
To*
I Debug
:
.
.
'
r, : v л • I . : : :
«
!
:
.
0
•
M
d
U
p
d
a
,
t
e
».=. S
t
a
U
s
t
l
c
s
.
v
b
[
D
e
>
l
g
n
]
|
*
*
x
|
1
1
I
.........
|
•!.
Й-':М!-!:.'[.'
' Tast; is£ Output Ready
t
•
i
:
:
•
•
•
•
•
: •
•
:
;
•
;
:
• ' • • • • ' :
:
'
:
'
:
•
•
;
ь
j[
A/c. ^.7. Форжв AddUpdateStatxstics
Обработка данных спортивной статистики
241
:> SuperStatsEntry - Microsoft visual BaiicJtET rdesion] - «HHUWMeBal
0e
E*. *>w fitoject guild
i С? Й £P I * ? > Г»...- E^ |
Qebug
Format
» [«bug
Tods
Jjjgrefaw
ЬФ
• I Q^LoadBatUngStaUsticsToUstVte/*
eaaiBtafistirs.vb* AddUpdateStetKti>5.»fc [Dsjign] AddUpdatcflattUcs.vb [Design] | О о
• И SJJ
?
i >• x
DK :::::*
• At Ba»s
Cancel
• Home Runs Щ RBI't
Ready
Рйс. /i.
E*
S U 0 I
Bew
k l
Его*»
6u«d
.
Visual Важ.Н£Т [design] - AddUpdatePfoh
>
: LoadBatmgStatsitc isToLsitVe iw
AJdUpdal<--BaU.ny...tK.i.vb [D
AddUpdalePilch..Jcs.yb [Design]|
- •"• »'ШЦ
«Add or Opddle Pildiine SlattHfc»t
• Starts p.; Runs
Losses. Sayes
аЛ List
Output
Ready
Puc.A.9. Форма AddUpdatePitchingStatistics, полученная из AddUpdateStatistics
242
Приложение А. Приложение Windows Form
Для корректного использования формы основного класса необходимо выполнить следующие действия: определить, что событие btnOK_Click может быть отменено дочерним классом, а также создать новые свойства текстовых полей Years и Games. Необходимый для этого код приведен в листинге А.6. Листинг А.6. Объявление события btnOK_Click и свойств производных классов форм Protected Overridable Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click End Sub Protected Property Year() As Integer Get Return CInt(txtYear () .Text) End Get Set (ByVal Value As Integer) txtYear().Text = Value.ToString End Set End Property ' Protected Property Games() As Integer Get Return CInt(txtGames().Text) End Get Set(ByVal Value As Integer) txtGames().Text = Value. ToString End Set End Property
Резюме В этом примере продемонстрирован ряд элементов, использование которых позволяет расширить библиотеку Windows Forms и значительно ее улучшить. Взяв этот пример за основу, введите новые функциональные возможности, которые позволят вам лучше узнать свойства .NET Framework. Единственное, что остается сделать для создания действительно "пуленепробиваемого" приложения, — написать обработку исключительных ситуаций. В этом примере применяется несколько способов наследования. Например, использованы типизированные наборы данных DataSet, полученные из класса DataSet библиотеки классов. С помощью визуального наследования созданы два диалоговых окна, используемые для сбора статистических данных. Кроме этого, добавлен новый элемент управления Treeview, использующий объекты TreeNode, наследованные из базового класса Т re eNode. В приложении Б, "Web-служба ASP.NET и приложения Web Forms", описывается компонент промежуточного уровня, используемый в качестве иллюстрации приложения WebFormASP.NET.
Резюме
243
Web-службаASP.NET и приложения Web Forms Итак, вы уже познакомились с приложением Windows Forms. Теперь рассмотрим три связанных приложения. Одно из них — Web-служба ASP.NET — использовалось в предыдущем примере на промежуточном уровне. Кроме этого, здесь описывается два приложения Web Forms ASP.NET, использующие одну и ту же Web-службу (вернее, набор служб). Полный код можно найти по адресу: www.williamspublishing.com. Web-служба обеспечивает доступ к базе данных бейсбольной статистики SQL Server 2000, о создании которой речь шла в приложении А. Одно из приложений Web Forms предоставляет пользователю возможность изменить статистические данные, связанные с бейсболом, непосредственно во время бейсбольного матча. Это приложение представляет собой простую одностраничную Web-форму, демонстрирующую широкие возможности элемента управления DataGridASP.NET. Второе приложение Web Form является примером одного из возможных применений общедоступной Web-службы. В нем некое вымышленное лицо (назовем его Бобом) использует Web-службу для отображения статистических данных, касающихся игроков, на вымышленном бейсбольном узле. Компоненты среды .NET Framework, используемые в данном проекте, показаны на рис. Б.1.
Visual Basic
JГ
C#
C
JScript
Языки стороиних'Ч разработчиков J
C++
Спецификация единого языка
nIe trnetExp ole rr С
Основные компоненты среды исполнения .NET ASP.NET
"I
if Web-службы
Web Forms
Элементы управления
Оболочка Консольные] I Windows 1 приложения J I Forms
( Службы NT J
Базовые классы .NET Framework
Единая среда исполнения (Управление памятью)
(
Сборка мусора
)
(
)
(
Рис. Б.1. Компоненты .NET Framework, используемые в рассматриваемом проекте
Web-служба спортивной статистики Промежуточный уровень, описанный в этом или предыдущем примере, обслуживается приложением Web Service ASP.NET. Web-служба состоит из общедоступного набора методов, которые обеспечивают доступ для чтения к базе данных SuperStats. На рис. Б.2 показана база данных SQL Server 2000, используемая в этом приложении. Кроме того, данный набор методов позволяет ограничить использование служб, предоставив необходимые права доступа только внутренним пользователям. (Описание защиты Web-служб выходит за пределы этой книги.) На рис. Б.З иллюстрируется общедоступная Web-служба, а на рис. Б.4 — закрытая Web-служба. Web-служба SuperStats состоит из двух . ASMX-файлов, содержащих Web-методы. Рассмотрим один из Web-методов. Код, приведенный в листинге Б.1, иллюстрирует один из наиболее сложных методов Web-службы. Этот код используется для формирования сложного набора данных D a t a S e t , показанного на рис. Б.5. ЛИСТИНГ Б.1. Web-метод GetTeamsAndPlayers <WebMethod (). > _ Public Function GetTeamsAndPlayers() As TeamsAndPlayers Dim oConnection As SqlConnection = New 4>SqlConnection("server=localhost;uid=sa;pwd=,• 4>database=BaseBallStatistics") Dim DS As New TeamsAndPlayers() Dim oDataAdapter As SqlDataAdapter oConnection.Open()
246
Приложение Б. Web-служба ASP.NET и приложения Web Forms
FK_lbWi:hers_tblTeams tbPiteNngStagstics [ J Player ; ITeam
FK_lblTeaniWayers_tblTeaiiK
_ Player I | Team
I TeamD I JPtaywm
FK_tblBattsr5_tbPlayers
tHPtayers* [f|
Puc. £.2. Диаграмма базы данных SQL Server 2000
Web-служба спортивной статистики
247
Fie Edti Ve iw Favorties Toosl Heb
Personal8
* J~> Seech . ,<|f F«vor*es 0 | 0 VJ Q Oo I Ln iks Address [
The following operations ere supported. For a formal definition, please review the Pe*,q;ril>Upft. • GBtRBIt.cad.erE
• GetERALeaders
This web service Is using http://tempurl.org/ as its default namespace. Recommendation: Change the default namespace before the web service Is made public. Each web service needs a unique namespace to identify it so that client applications :an distinguish it from other services on the web. http://tempun.urg/ is available for wet services that are under development, but published web services should use a more permanent namespace. Your web service should be identified by a namespace that you control. For example you could use your companys' Internet domain name as part of the namespace. Although man/ web service namespaces look like URLs, they need not point to an actual resource on the web. (Web service namespaces are URis.) For ASP.NET Web Services, the default namespace can be changed using the WebServc ie attribute's Namespace property. The WebServtce attribute is an attribute applied to the class that contains the web service methods. Beo l w is a code exampe l that sets the namespace to н
П
/
/
*
Й
Л
Ь
/
"
[ *Sj local intranet
Рис. Б.З. Общедоступная Web-служба
248
Приложение Б. Web-служба ASP.NET и приложения Web Forms
3l DataBase Access Web Service - Microsoft internet Explorer Fie Edit View Favorites Tools Help -
DataBaseAccess The following operations are supported. For a formal definition, please review the Service Description,
This web service is using http://tempurl.org/ as its default namespace. Recommendation: Change the default namespace before the web service is made public. Each web service needs a unique namespace to identify it so that client applications can distinguish it from other services on the web. http:/Aempuri,org/ is available for web services that are under development, but published web services should use a more permanent namespace. Your web service should be identified by a namespace that you control, For example, you could use your company's Internet domain name as part of the namespace. Although many web service namespaces look like URLs, they need not point to an actual resource on the web. (Web service namespaces are UPIs.) For ASP.NET Web Services, the default namespace can be changed using the WebService attribute's Namespace property, The WebService attribute is an attribute applied to the class that contains the web service methods, Below is a code example mat sets the namespace to "http://microsoft.co m/webservices/": C# [VebService: (N«u«apace-*"http://microsoft.com/webservices/*)] public class HyUebSetvice i . // implementation У
V i s u a l
'
.
•
.
'
•
:
.
•
•
•
-
.
.
, , :
•
B a s i c . N E T
3
*
J
L o c a l
' n t r a n e t
Рис. Б.4. Закрытая Web-служба
Web-служба спортивной статистики
249
- Microsoft Visual Basic.NET[design] - leamsAni Edt Se» Project
й'Ьид
Ш• I * Я 0|
в j ••••> • О - JB - 1 ^ | > Debug
Sjhema
loots
Window
Help
Start Page | DataSaseAccess.asw i .vb" j DstaBas-iAccess.asfnx.vb tDesg i nJ* j 5upef5fcats,asm* < • ££ ID string E TearnName string f: League string
Sypayws • J: 1
r;Г FLastfjame islName F BilthDate E Height
string string string date Time int
л — »
ly^attingStatisMBattingStatlstii 5) t:К PlTeam ayw К rear F Games
O
:
string string string int int
.J -1
HSr^chingStMlstifRtcNrnjStatis Jcs) VE ID string E Player string J E Team string — int E Year ! Games M zl
-till
Рис. Б.5. Набор данных TeamsAndPlayers в окне конструктора схем Код, приведенный в листинге Б.1, содержит целый ряд вспомогательных функций (т.е. функций, вызывающих цепочку других функций). Одна из таких функций используется в листинге Б.2 для создания SQLDataAdapters каждого из объектов DataTables ADO.NET, которые будут сгенерированы для набора данных DataSet. Вспомогательная функция создает командные объекты и назначает их командам SelectCommand, InsertCommand, UpdateCommand и DeleteCommand. Для получения доступа к данным эти команды используют хранимые процедуры. Аналогичные вспомогательные функции также используются Web-методом UpdateTeamsAndPlayer. ЛистингБ.2. Метод CreateTeamPlayersAdapter Private Function CreateTeamPlayersAdapter(ByRef oConnection As SqlConnection) As SqlDataAdapter Dim oDataAdapter As New SqlDataAdapter() Dim oCommand As SqlCommand oCommand = New SqlCommand() With oCommand .CommandType = CommandType.StoredProcedure .CommandText = "GetTeamPlayers" .Connection = oConnection 250
Приложение Б. Web-служба ASP.NET и приложения Web Forms
End With oDataAdapter.SelectCommand = oCommand oCommand = New SqlCommandO With oComraand .CoramandType = CoramandType.StoredProcedure .CommandText = "InsertTeamPlayer" .Parameters.Add(New SqlParameter("@id", SqlDbType.Uniqueldentifier, 16, System.Data.ParameterDirection.Input, True, 0, 0,"ID",System.Data.DataRowVersion.Original, Nothing)) .Parameters.Add(New SqlParameter("@TeamID", SqlDbType.Uniqueldentifier, 16, System.Data.ParameterDirection.Input, True, 0, 0, "TeamID", System.Data.DataRowVersion.Original, Nothing)) .Parameters.Add(New SqlParameter("@PlayerID", SqlDbType.Uniqueldentifier, 16, _ System.Data.ParameterDirection.Input, True, 0, 0, "PlayerlD", System.Data.DataRowVersion.Original, Nothing)) .Connection = oConnection End With oDataAdapter.InsertCommand = oCommand oCommand = New SqlCommand() •
W
i
t
h
o
C
o
a
n
d
C
o
m
m
a
n
d
T
y
p
e
.
C
o
m
m
a
n
d
T
e
x
t
.
P
a
r
P
a
a
m
C
s
t
e
m
.
D
a
t
a
s
t
e
m
.
D
a
t
a
d
y
s
t
o
D
a
t
a
o
C
o
m
m
W
i
t
m
A
q
l
y
s
t
t
.
D
s
T
e
l
c
t
i
o
p
t
e
r
y
n
r
l
=
o
d
.
=
w
a
n
d
a
n
d
T
y
p
e
=
.
C
o
m
m
a
n
d
T
e
x
t
=
.
C
o
"
C
m
e
t
e
r
s
.
t
S
m
a
m
a
m
r
m
e
d
o
a
o
N
p
C
P
C
U
.
.
D
.
S
t
m
P
l
a
l
l
q
f
r
l
P
s
a
f
e
a
i
d
e
c
m
t
.
e
r
i
O
t
r
P
(
o
c
e
d
u
r
e
S
T
e
a
m
P
l
a
"
6
o
.
i
r
I
g
(
,
"
1
6
n
p
u
t
e
,
i
n
a
l
,
r
@
T
e
a
m
I
T
N
D
r
o
"
u
t
a
m
e
t
e
r
D
i
r
e
c
t
i
o
n
.
I
n
p
u
t
,
s
t
e
m
.
D
a
t
a
.
D
a
t
a
R
o
w
V
e
r
s
i
o
n
.
C
"
@
P
l
a
y
e
r
I
D
"
,
r
s
e
l
a
,
n
d
m
n
l
e
e
P
n
a
t
r
i
f
a
i
m
e
e
r
t
e
r
(
,
1
6
e
r
D
i
r
e
c
t
i
o
n
.
I
n
p
u
t
,
e
m
.
D
a
t
a
,
D
a
t
a
R
o
w
V
e
y
s
t
e
c
t
i
o
p
d
a
t
e
l
D
"
,
i
0
,
n
g
)
r
r
e
C
u
r
,
0
,
"
I
D
"
h
i
n
,
)
T
r
u
e
0
,
u
,
n
t
,
e
n
N
o
t
g
)
)
,
t
S
U
,
y
q
o
e
h
r
S
T
,
T
r
i
u
o
e
n
0
,
.
,
r
t
,
N
o
t
h
i
n
g
)
)
n
A
d
e
q
C
l
C
"
d
(
N
o
D
e
m
e
m
a
m
a
d
n
=
d
o
a
n
d
T
y
p
e
.
l
e
t
e
T
e
a
m
P
S
l
d
q
e
l
n
o
m
m
a
n
d
P
t
a
i
r
f
S
a
m
e
o
a
y
e
r
t
r
e
d
P
r
e
e
r
r
,
o
c
e
d
u
r
e
"
(
1
"
6
@
T
T
y
p
e
.
U
S
y
s
t
e
m
.
D
a
t
a
.
P
a
r
a
m
e
t
e
r
D
i
r
e
c
t
i
o
n
.
I
n
S
y
s
t
e
m
.
D
a
t
a
.
D
a
t
a
R
o
w
V
e
r
s
i
o
n
.
O
r
i
g
i
n
e
c
t
i
o
C
o
n
n
e
c
t
i
o
n
Web-служба спортивной статистики
i
t
l
b
=
e
C
O
m
w
u
n
D
n
q
o
m
l
o
i
C
m
q
n
n
o
S
n
y
,
n
r
e
r
"
1
n
e
e
r
,
e
o
r
e
t
r
r
i
r
i
m
e
i
r
t
a
i
D
e
n
r
i
e
V
e
a
t
t
w
d
P
n
o
y
S
r
o
e
a
S
u
a
p
e
e
o
w
q
P
m
R
e
e
i
.
y
T
e
w
a
T
e
q
d
a
a
u
N
n
a
e
P
(
U
t
e
q
d
t
l
r
t
,
d
.
a
N
.
e
a
a
i
"
d
e
a
a
D
A
D
(
n
n
a
S
u
P
D
a
d
w
q
.
m
p
e
i
.
d
t
N
n
U
I
p
.
P
a
.
y
m
d
.
m
(
U
A
e
a
r
b
t
.
p
e
.
m
U
h
a
o
m
e
D
s
y
T
"
e
n
h
e
,
d
a
e
S
r
T
"
S
i
e
b
,
n
W
t
D
a
n
e
l
e
d
y
m
p
d
y
q
y
A
S
a
T
.
S
r
o
s
b
0
.
r
D
r
a
e
o
"
l
0
P
t
C
q
S
.
e
=
=
S
S
n
m
.
.
E
m
e
a
m
P
p
u
t
,
a
l
,
,
l
a
y
e
r
I
D
"
,
_
T
N
r
o
u
t
e
,
h
i
0
n
g
,
)
0
,
"
I
D
"
,
)
251
End With oDataAdapter.DeleteCommand = oCommand Return oDataAdapter End Function Особый интерес представляет способ, используемый ADO.NET для поддержки конкурентного доступа к данным. Для этого созданы две обновляемые хранимые процедуры с оптимистической моделью доступа (не проверяется изменение данных перед их обновлением). Используйте значение параметра s o u r c e V e r s i o n для определения версии поля, переданного параметру хранимой процедуры. Наиболее распространенными значениями, передаваемыми этому параметру, являются S y s t e m . D a t a . D a t a R o w V e r s i o n . O r i g i n a l и S y s t e m . D a t a . D a t a R o w V e r s i o n . C u r r e n t . Значение O r i g i n a l говорит ADO.NET о передаче того значения поля, которое было первоначально получено из базы данных. Значение C u r r e n t , в свою очередь, говорит ADO.NET о передаче хранимой процедуре текущего значения поля. Эти значения могут быть использованы для передачи любого числа параметров базе данных для управления конкурентным доступом с помощью одного из наиболее распространенных методов. • Использование метки даты/времени. Этот метод применяется чаще всего. Его основная идея состоит в обновлении метки даты/времени при каждом изменении строки, что позволяет, обратившись к полю временной метки хранимой процедуры, убедиться в том, что выбранная метка точно такая же, как и метка строки. • Передача меток всем полям. Для того чтобы убедиться, что данные полей соответствуют первоначальным данным, полученным из базы данных, сравните временные метки полей. Остальные Web-методы создают наборы данных без контроля типов D a t a S e t , которые возвращают данные хранимых процедур.
Обработка статистических данных Первое созданное приложение Web Form ASP.NET позволяет корректировать статистические данные текущего сезона бейсбольной лиги. Это приложение представляет собой простую одностраничную Web-форму, но в то же время демонстрирует широкие возможности ASP.NET и элемента управления DataGrid ASP.NET. Web-форма в различных режимах показана на рис. Б.6 и Б.7. ASP.NET позволяет значительно упростить управление поведением формы. Для этого достаточно открыть окно Property Builder элемента управления DataGrid, щелкнув на указанном элементе правой кнопкой мыши и выбрав из контекстного меню команду Property Builder. Свойства элемента управления D a t a G r i d должны быть установлены в соответствии с параметрами, показанными на рис. Б.8. После установки свойства столбца необходимо определить события серверного приложения для кнопок Edit, Cancel и Update. В листинге Б.З приведен код обработчиков событий, созданных для обработки событий элемента управления DataGrid: •
EditCommand — переключение сетки в режим редактирования;
•
CancelCommand — возврат сетки в режим просмотра;
•
UpdateCommand — внесение изменений в базу данных.
252
Приложение Б. Web-служба ASP.NET и приложения Web Forms
Э http: '/red каЛм?.,Superstate ivrt r\iry/imlcn.a«p» - Microsoft Inter net rxplorer Fie
Ц http./red-teader2/superstatsiive£nti-y/Iide>ui«r»< - Microsoft Internet explorer File Edit. Veiw Favorties Toosl . Hep i • •* • 4? j] 4t ' [CPMSonae l ar J^Seaci h jjFavoritK •£ -_j- Jt Z} Л | Address j*]fittP://'ed-teadeO'SupeiStatsuveEntiy/Index.aspx
Л/с. Ь1.7. Web-форма в режиме редактирования (после щелчка на кнопке Edit)
254
Приложение Б. Web-служба ASP.NET и приложения Web Forms
gridPtayersStatirtits Properties iO General ррСокетм
"§. Paging [*4 Format 'ЕВ «в*»»'
fv* Create coulmns automstcl&ty at run line Cou l mnsit — — — B ouc no du Con lus m n AЯvaa liQИbe lButton lm : Sebscted coulmns: Column ! • S3 Select 'i
Convert this column into ь Tenipiate Column Cancel
Help
Рис. Б.8. Окно Property Builder элемента управления DataGrid ЛИСТИНГ Б.З. Код обработки событий сервера для элемента управления DataGrid
Protected Sub OnGridPlayersStatisticsEdit(ByVal sender As System.Object, ByVal e As DataGridCommandEventArqs) _ Handles gridPlayersStatistics.EditCommand Call BindGridDataSource(dropTeams() .Selectedltem.Value) gridPlayersStatistics().Editltemlndex =• e.Item.Itemlndex gridPlayersStatistics () .DataBind() End Sub Protected Sub OnGridPlayersStatisticsCancel(ByVal sender As _ System.Object, ByVal e As DataGridCommandEventArgs) Handles gridPlayersStatistics.CancelCommand Call BindGridDataSource(dropTeams().Selectedltem.Value) gridPlayersStatistics().Editltemlndex = -1 gridPlayersStatistics().DataBind() End Sub Protected Sub OnGridPlayersStatisticsUpdate(ByVal sender As System.Object, ByVal e As DataGridCommandEventArgs) _ Handles gridPlayersStatistics.UpdateCommand If dropPlayerType().Selectedltem.Value = "1" Then Call UpdateBattingStatistics(e) Else Call UpdatePitchingStatistics (e) End If Call BindGridDataSource(dropTeams().Selectedltem.Value) gridPlayersStatisticsO.Editltemlndex = -1 gridPlayersStatistics().DataBind() End Sub Обработка статистических данных
255
Особый интерес представляет также и оставшаяся часть кода. (Для того чтобы увидеть, как происходит получение обновленных значений, обратитесь к методу UpdateB a t t i n g S t a t i s t i c s или U p d a t e P i t c h i n g S t a t i s t i c s . ) Теперь можно создать пример приложения, использующего Web-службу.
Узел бейсбольной статистики В Internet находится достаточно большой объем статистическкх данных, относящихся к спорту, в частности к бейсболу. Поэтому, для получения доступа к этим данным вымышленная компания (SuperStats) должна воспользоваться Web-службой. Второе приложение Web Form представляет собой начальную страницу бейсбольного узла, использующего целый ряд различных Web-служб. Приложение, открытое в окне Internet Explorer, показано на рис. Б.9 и Б. 10. ahttp:/rPd-lcader2/Bob«Fanta*yBa$pbaH/WebformI^»px-Mi£3ro»of t Inter net Explorer : File Edti Ve iw Favorties Toosl Hep l ., JjBacr; - ** ' ^ |^ *£} I 1УРУ serai Bar i^Seafch ^JFavwites (^ j b^* ^i ^ J$ ^ Address |O] htp://red-h!ad;ir2/eotnFartiasyBaseba/lWebForm.laspx
_ j^j
jsialls Itcs Юг 2001 Regular Season^]
National League Players
RBI leaders Wins Leaders
Рис. Б.9. Узел бейсбольной статистики
256
Приложение Б. Web-служба ASP.NET и приложения Web Forms
rZ/0<*tf лп»муВж>рЬ«8ЛИеЫогт»лч»' - Microsoft 1
Ed* Vim FevorKK Toosl Hep l ;k » ;"* » t£) (з5 t2 1 Q^Pertonaleer '^Se*di ^Favorite* Address |C] T.Kp^/rtd-lssti-rJ.IBobsFa^eivBsitbalfA'fbForml .asp:
^
_ j - _ > 7.':
J
tlatlsltos lor imiRcgular Seastn ^] nLeague Wavers
Рис. Б. 10. Лидеры Американской лиги
"Изюминка" приложения заключается в том, что все его данные получены из внешнего источника с помощью Web-служб и протокола SOAP. Для отображения данных при создании таблицы снова используется элемент управления D a t a G r i d ASP.NET. В листинге Б.4 приведен код для каждой из гиперссылок, расположенных в левой части страницы. ЛИСТИНГ Б.4. Код загрузки элемента DataGrid
Protected Sub lnkNLBattingAverage_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles lnkNLBattingAverage.Click Dim iYear As Integer - CInt(dropYear().Selectedltem.Value) gridPlayers().DataSource = _ databaseaccess.GetBattingAverageLeaders("NL", iYear) Page().DataBind() End Sub Для создания Web-формы необходимо всего лишь добавить две панели Web Form (вверху и слева). Затем следует для создания меню вынести несколько кнопок гиперссылок на левую панель страницы. Введите код обработки событий, приведенный в листинге Б.З, и перетащите на форму элемент управления DataGrid. После этого отформати-
Узел бейсбольной статистики
257
руйте форму, щелкнув на ней правой кнопкой мыши и выбрав из контекстного меню команду AutoFormat. Диалоговое окно AutoFormat показано на рис. Б. 11. , Это приложение также позволяет выполнить регистрацию пользователя для получения обновленных данных по электронной почте. Это пример стандартного Coo l rful 3 процесса регистрации, для выполнения Colorful 4 Colorful 5 которого необходимо ввести адрес элекProfesso i nal1 Professo i nal2 тронной почты и имя пользователя. ФорProfesso i nal3 Sm i pe l1 ма, используемая для регистрации посетиmpel 2 теля, показана на рис. Б. 12.
Рис. £.11. Диалоговое окно AutoFormat
File Edti Ve iw Favorties Toosl Hep l -^l»:l - •• J _J i j ГХ[е"':м1ь>' Address { i j Ы>[, r/red-leader2/8obsF«ntas,iDaseball/U
»!•>•-Mc i rosoft Internet txptawa„jjFavaite
F. fila (is I ics tor 2001 Refrtar
HeilMLeadfLS Eanino Averse leaders Register
National League Players 'aitir.g Average Leaders RBILsadtrs Vins Leaders iiassliileps
Рис. Б. 12. Форма электронной регистрации
258
& local n i bann
Приложение Б. Web-служба ASP.NET и приложения Web Forms
В листинге Б.5 приведен код события C l i c k , при выполнении которого происходит ввод регистрационной информации в базу данных (с помощью параметров хранимой процедуры другого класса). Листинг Б.5. Событие Click кнопки btnRegister Protected Sub btnRegister_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRegister.Click Dim sFirstName As String Dim sLastName As String Dim sEmail As String sFirstName = txtFirstName().Text sLastName = txtLastName().Text sEmail = txtEmail().Text BobsFantasyBaseballDBA.AddRegistration(sFirstName, sLastName, sEmail) Call HideRegistration() Call ShowALPlayers() End Sub Для проверки заполнения пользователем всех полей ввода регистрационной формы используется элемент управления R e q u i r e d F i e l d V a l i d a t o r ASP.NET, который позволяет проверить правильность данных, введенных в соответствующие поля формы. В том случае, если пользователь попытается выйти из окна ввода, нажав клавишу <ТаЬ> или щелкнув мышью на кнопке Register, будет отображено то или иное сообщение. Этот пример наглядно демонстрирует простоту и гибкость одной из новых возможностей ASP.NET.
Резюме В этом приложении вы познакомились с целым рядом элементов, использование которых выводит новую платформу разработки ASP.NET на качественно новый уровень. Никогда еще не было настолько просто создавать высокодинамические приложения для Internet. Соедините это с новыми возможностями Web-служб — и третье поколение приложений Internet станет реальностью. В приведенных примерах использован новый элемент управления DataGrid ASP.NET, позволяющий отображать и редактировать данные. Этот элемент принадлежит к числу новых невероятно мощных серверных средств управления ASP.NET. Visual Studio.NET и описанные элементы управления позволяют добавить известный разработчикам Visual Basic метод создания приложений в виде Web-служб и Web-форм.
Резюме
259
Предметный указатель
Abstraction, 44 Active Server Pages (ASP), 80 ADO, 155 ADO.NET, 156 API Windows, 194 .ASMX-файл, 245 ASP.NET, 81; 186 Assemblies, 17 Attributes, 67
В BizTalk Server 2000, 187 Boxing, 118
C#, 38 Cascading Style Sheet, 37 Classes, 44 COM (Component Object Model), 16 COM Callable wrapper (CCW), 199 COM Interop, 231 COM+, 15 Commerce Server 2000, 187 Common Gateway Interface (CGI), 81 Common Language Runtime (CLR), 19; 191; 193 Common Language Specification (CLS), 111 СОМ-компоненты, 41 Constructors, 69
DAO, 153 Discovery of Web Services (DISCO), 191 DLL-кошмар, 15 Dynamic Help, 29
E Encapsulation, 45 Events, 57 Exchange Server 2000, 187 260
H Hailstorm, 230 Hailstorm WebServices, 189 HasA, 48 Host Integration Server 2000, 187
I IDL (Interface Definition Language), 17 Implementation inheritance, 49 Initializers, 69 Integrated Development Environment (IDE), 27 IntelliSense, 27 Interface, 45 Intermediate Language (IL), 20 Internet Information Server (IIS), 81 IsA, 48
Just- In-Time compilation, 19
L Late binding, 46 Loosely Coupled Event Service (LCE), 213
M Managed code, 19 Manifest, 18 Menu Editor, 33 Metadata, 18 Methods, 44; 57 Microsoft Expedia, 230 Microsoft Message Queue (MSMQ), 205 Microsoft Instant Messenger (MIM), 230 Microsoft Passport, 230 Пзедметный указатель
Microsoft Transaction Server (MTS), 193 Mobile Information Server 2001,187 MSDN, 27 MTS (Microsoft Transaction Server), 15 myAddress, 230 myApplicationSettings, 231 myCalendar, 231 myContacts, 231 myDevices, 231 myDocuments, 231 my Favorite WebSites, 231 mylnbox, 231 my Location, 231 myNotifications, 231 my Profile, 231 my Services, 231 my Usage, 231 myWallet, 231
N Nested type, 121 Next Generation Web Services (NGWS), IS .NET Framework, 15 .NET Security, 177
О
Type safety, 47 Type Lib, 200
и Unboxing, 118 Unicode-строки, 120 Universal Description, Discovery and Integration (UDDI), 191 Unmanagedcode, 19
Value types, 112 Version policy, 21
w Web Services Description Language (WSDL), 191 WebClasses, 217 Web-службы, 38; 92; 230 Windows DNA, 186 Windows DNA 2000, 186 Windows Form, 233 Windows Forms, 96
Оператор Declare, 194 Do Loop Until, 135 Do While Loop, 135 ELSEIF, 127 Event, 64 Exit Try, 139 For Each, 131 For Next, 130 GoTo, 136 IF, 126 On Error, 137 On Error Goto, 136 OrElse, 126 Property Get, 61 Property Let, 60 Property Set, 60 Remove Handler, 65 Return, 58 Select Case, 128 Structure, 123 Throw, 140 Try...Catch...Finally, 139 While End While, 136 Описание исключения, 139 Определение интерфейса, 53 Оптимизированные библиотеки классов, 226 Организация очереди, 208 очереди компонентов, 206 пула объектов, 211 пула подключений, 206 Очередь сообщений, 205
п Пакетирование, 118 Пакетные обновления, 159 Перегрузка, 59; 70 Песочница Java, 175 Позднее связывание, 46 Полиморфизм, 46 Политика контроля версий, 21 Политики,177 Получение набора данных, 158 Пользовательский тип исключения, 143 Порядок выполнения команд, 126 Правила передачи параметров, 195 Правильное использование обработчика исключений, 147 Предложение Catch, 139
264
Finally, 140 Try, 139 Прекомпилятор, 20 Приложения ActiveX EXE, 218 DHTML, 218 IIS, 217 Проверка идентичности, 177 Проект ActiveX DLL, 75 ActiveX EXE, 75 Class Library, 75 Web Forms, 81 WebClasses, 81 Проекты данных, 218 Просмотр классов проекта, 29 Просмотр проектов, 29 Пространство имен, 21; 156 Протокол простого доступа к объектам,190 Процедурный стиль программирования, 40 Пул объектов, 209
Свойства наследования, 80 Свойство ContextMenu, 239 Instancing, 72 Read-Only, 61 Write-Only, 61 заданное по умолчанию, 61 общедоступное, 62 Сервер .NET Enterprise, 188 Сигнатура, 59 Синхронизация,206 Система безопасности .NET Security, 41 Система удаленной безопасности, 178 Служба слабосвязанного события, 213 Службы Windows, 75; 107 Службы транзакций, 206 Событие CancelCommand, 251 Classjnitialize, 69 Class_Terminate, 71 EditCommand, 251 Page Load,83 Popup, 240 UpdateCommand, 251 Создание, 66 Сопровождение, 81 Спецификация единого языка, 111 Ссылочный тип, 114 Строгие имена, 199 Строгий контроль типов, 170 Строки фиксированной длины, 120 Структурная обработка исключений, 138 Структурная обработка ошибок, 41 Структуры, 124 Схема XSD, 170 Счетчики производительности, 31
Object, 114; 120 Single, 113 String, 120 Variant, 120 вложенный, 121 определяемый пользователем, 113 Типы проектов, 217 Типы связей между объектами иерархии,48 Транзакции СОМ+, 208
Удаленные элементы языка, 219 Узел Performance Counters, 31 Узлы дерева, 238 Упаковщик времени выполнения, 202 Управление версиями, 20 Управляемая куча, 182 Управляемый программный код, 19 Управляющая среда, 19 Уровень бизнес-правил,186 представления, 186 хранения данных, 186 Уровни доступности классов, 72 Уровни доступности методов и свойств, 73
Ф Функция CSTR, 112 CTYPE, 113 Format, 113
Хэширование, 22 Технология Platform Invoke, 194 Технология подсчета ссылок, 180 Тип Boolean, 112 Boxed Types, 118 Char, 120 Class, 120 Currency, 120 Date, 119 DateTime, 119 Decimal, 120 Double Floating Point, 113 Integer, 112; 120 Long, 120 Предметный указатель
ц Цели разработки VB.NET, 38 Циклические ссылки, 180 Циклы, 129
Численные типы, 111
265
TIT Шаблон Class Library, 77 Console Application, 109 Web Application ,81 Web Control Library, 86 Web Service, 92 Windows Application, 96 Windows Control Library, 102 Windows Service, 107 Шаблон проектирования Dispose, 71 3 Элемент управления
266
DataGrid, 244 ASP.NET Web Form, 86 Web Control, 106 Windows, 102 a Явная обработка исключительных ситуаций, 141 Явное приведение типов, 41 Язык Intermediate Language, 20 описания Web-служб, 191 описания интерфейсов, 47 Язык определения интерфейсов, 17
Предметный указатель
Научно-популярное издание
Кит Франклин
VB.NET для разработчиков
Литературный редактор Верстка Художественный редактор Технический редактор Корректор
Т.П. Кайгородова М. А. Удалое В. Г. Павлютин Г. Н. Горобец 3. В. Александрова
Издательский дом "Вильяме". 101509, Москва, ул. Лесная, д. 43, стр. 1. Изд. лиц. ЛР № 090230 от 23.06.99 Госкомитета РФ по печати. Подписано в печать 17.01.2002. Формат 70x100/16. Гарнитура Times. Печать офсетная. Усл. печ. л. 21,93. Уч.-изд. л. 14,92. Тираж 5000 экз. Заказ № 2594. Отпечатано с диапозитивов в ФГУП "Печатный двор" Министерства РФ по делам печати, телерадиовещания и средств массовых коммуникаций. 197110, Санкт-Петербург, Чкаловский пр., 15.
Использование Linux. Специальное издание, 6-е издание Впродаже
Э
ту книгу должен прочитать каждый, кто намерен впервые устанавливать Linux. Она должна быть настольной книгой пользователя. Полезной она будет и для системных администраторов, работающих с Linux или Unix, даже если они лихие профессионалы и признанные гуру. Книга рассчитана на новичков, на тех, кто уже имеет некоторый опыт, и даже на опытных системных администраторов, т.е. на всех, кому приходится часто иметь дело с использованием и управлением Linux. Книга, возможно, не оправдает ожидания хакеров от Linux или "спецов" по Unix. И хотя она станет незаменимым пособием для тех, кто хочет больше узнать о Linux н Unix, с ее помощью нельзя будет поднять свой уровень выше пользовательского. В книге нет заумных советов и сверхсложных объяснений. Она, скорее, состоит из "изюминок". Аиторы сочли возможным не затрагивать некоторые темы, так как их полное рассмотрение требует чрезмерной детализации. Те, кого интересуют тонкости работы и настройки Linux, могут без труда отыскать другое, более специализированное пособие. Это касается и других вопросов, ответы на которые можно найти в книгах, рассчитанных на пользователей разного уровня. Тем не менее книга будет полезна даже тем, кто уже знаком с процессом установки Linux и работал с Unix. Особенно если до этого использовалась только система Unix и не приходилось сталкиваться с задачами системного администрирования. Некоторые разделы специально посвящены тонким моментам системного администрирования с использованием Linux/UNIX. Книга рассчитана на пользователей с различным уровнем подготовки.
Кент Джоши и Software Spectrum Inc.
Использование Microsoft Exchange 2000 Server. Специальное издание Впродаже
Иига посвящена продукту Microsoft Exchange 2000 Server и написана на основе практического опыта сотрудников k нескольких компаний. Три наиболее известных консалтинговых компании, которые в сумме обладают практическим опытом установки более чем 20 миллионов рабочих мест Exchange, объединили свои усилия при создании нового руководства мирового уровня. Авторы книги, являясь ведущими специалистами в области обмена сообщениями из компаний Lucent, Compaq и Software Spectrum, самоотверженно трудились, чтобы передать читателям свой опыт, накопленные знания и материалы компаний обо всех аспектах применения Exchange 2000. Книга рассчитана на пользователей средней и высокой квалификации.
Гордон Падвик
Использование Microsoft Outlook 2002. Специальное издание Впродаже
I^^JtpeR вами книга, посвященная новой версии одного из т тсамых. популярных продуктов компании Microsoft — * Щ: Outlook 2002. В этой книге вы найдете подробное описание всех новых возможностей программы, а также основных приемов работы с ней. Вы научитесь использовать Outlook для работы с электронной почтой, управления вашей персональной информацией, а также в качестве клиента Microsoft Exchange Server. Подробно рассмотрены вопросы, связанные с использованием различных элементов Outlook, такими как контакты, заметки, сообщения электронной почты и задачи. Книга предназначена для пользователей средней и высокой квалификации.
lists-":
Освой самостоятельно ASP.NET за 21 день Плановая дата выхода 2 кв. 2002 г.
Д
SP.NET — это аббревиатура от названия нового программного продукта и новой технологии компании Microsoft, предназначенных для создания динамических Web-страниц и Web-приложений. Однако не думайте, что ASP.NET — это простое обновление классической технологии ASP. Хотя в новом продукте предложена более совершенная модель программирования и созданы новые инструменты для ее реализации, но этим различие между ASP и ASP.NET не исчерпывается. Для совершенного овладения новой технологией нужно затратить некоторые усилия и время, и вот тут-то вам придет на помощь эта книга. В каждом из 21 уроков новая тема рассматривается так, как будто читатель не знаком ни с одной из технологий Web-программирования, но если вам приходилось ранее иметь дело с технологией ASP, то вы оцените разделы в конце каждой главы, посвященные различиям между классической и новой технологиями. Если вы готовы к освоению новых технологий, то эта книга станет вашим надежным помощником. Книга предназначена для пользователей средней и высокой квалификации.
Неил Рандалл, Деннис Джоунз
Использование Microsoft FrontPage 2002, Специальное издание Плановая дата выхода 2 кв. 2002 г.
Э
та книга посвящена изучению средств и возможностей приложения FrontPage 2002 для разработки Web-страниц и Web-узлов в Internet. FrontPage 2002 — это чрезвычайно мощное многофункциональное приложение с очень простым и понятным интерфейсом. Книга написана целым коллективом соавторов. Идея состояла в том, чтобы по каждому вопросу информация исходила действительно от профессионала. С помощью данной книги вы научитесь использованию средств FrontPage 2002 для создания и разработки собственных Webузлов, затрачивая на это минимум усилий, но с максимальной эффективностью; управлению, настройке и поддержания узлов на Web-серверах для обеспечения их регулярного обновления и удобства работы пользователей; использованию для редактирования Web-страниц других приложений Micrc soft Office XP; созданию динамических эффектов с использованием средств DHTML и сценариев. Книга предназначена для пользователей средней и высокой квалификации.