Аннотация
Новые компоненты Microsoft .NET могут работать с существующими
приложениям COM и COM+. Это позволяет создавать приложения .NET, которые
поддерживают транзакции, используют преимущества защиты на основе ролей
(role-based security) и взаимодействуют с очередями.
Цели:
- научиться использовать сервисы COM+ в Microsoft® .NET;
- создать компонент, использующий сервисы COM+;
- развернуть этот компонент.
Требования к программному обеспечению и к подготовке читателей
Чтобы извлечь максимальную пользу из этой статьи, необходимо:
- иметь опыт работы с Microsoft Transaction Server (MTS) и
программирования распределенных транзакций на Microsoft Visual Basic®
6.0;
- иметь опыт в применении защиты на основе ролей с помощью
сервисов COM+;
- иметь опыт в создании и использовании очередей на основе
сервисов COM+;
- хорошо знать классы .NET;
- уметь создавать консольные приложения .NET.
Использование сервисов COM+ в .NET
Возможно, вы уже использовали приложения COM + для хостинга
компонентов, написанных на Visual Basic или C++. COM+ предоставляет
множество полезных сервисов, в том числе транзакции, компоненты с
поддержкой очередей, активизацию по требованию (just-in-time
activation), защиту на основе ролей, общие (shared) свойства и т. д.
Один из наиболее привлекательных аспектов применения COM+ для хостинга
компонентов - возможность изменения поведения компонента без единой
строчки дополнительного кода (например, указать обязательность поддержки
транзакций компонентом, пометив ее как Required). Если для
COM+-компонента установить переключатель Required (рис. 1) в разделе
Transaction Support (в оснастке Component Services консоли MMC), этот
компонент всякий раз будет создаваться в контексте COM+-транзакции. А
когда компонент использует COM+-транзакции, все транзакции базы данных
обрабатывает Distributed Transaction Coordinator (DTC).
Рис. 1. Пример COM+-компонента, требующего транзакций
Настроить параметры защиты для компонента не сложнее, чем поддержку
транзакций. Вы можете указывать, какие компоненты или их методы доступны
тем или иным пользователям; перекомпиляции кода при этом не требуется.
Все это делается через оснастку COM+ Services.
.NET может работать со всеми сервисами COM+
В .NET Framework можно по-прежнему использовать все сервисы COM+,
если ваши классы наследуют от
System.EnterpriseServices.ServicedComponent. В табл. 1 перечислены
сервисы COM+, поддерживаемые в .NET.
Табл. 1. Доступные сервисы COM+
Сервис COM+ |
Описание |
Автоматическая обработка транзакций
(Automatic Transaction Processing) |
Применяет объявленные средства обработки
транзакций |
COM Transaction Integrator (COMTI) |
Инкапсулирует приложения CICS и IMS в
объектах Automation |
Диспетчеры компенсации ресурсов Compensating
Resource Managers (CRMs) |
Применяет к ресурсам, не поддерживающим
транзакции, свойства атомарности и отказоустойчивости |
Активизация по требованию (Just-In-Time
Activation) |
Активизирует объект при вызове метода и
деактивизирует его после возврата из этого метода |
Нежестко связанные события (Loosely Coupled
Events) |
Управляет событиями на основе объектов |
Конструирование объектов (Object
Construction) |
При создании экземпляра класса передает ему
постоянное строковое значение |
Поддержка пулов объектов (Object Pooling) |
Предоставляет пул готовых объектов |
Компоненты с очередями (Queued Components) |
Предоставляет поддержку очередей асинхронных
сообщений |
Защита на основе ролей (Role-Based Security) |
Применяет разрешения защиты в зависимости от
роли |
Общие свойства (Shared Properties) |
Обеспечивает совместное использование
информации о состоянии несколькими объектами в рамках серверного
процесса |
Синхронизация [Synchronization (Activity)] |
Управляет доступом к общим ресурсам |
Взаимодействие с XA (XA Interoperability) |
Обеспечивает поддержку модели обработки
транзакций X/Open |
Для чего нужны сервисы COM+ в .NET
Сервисы COM+, поддерживаемые в .NET, полезны при написании приложений
.NET, использующих транзакции, защиту на основе ролей и очереди. .NET
упрощает реализацию этих сервисов, как вы увидите в данном документе.
Совет Если вашему .NET-коду не требуется взаимодействие с
сервисами COM+ (т. е. планируется, что он будет работать исключительно в
.NET Framework), не используйте System.EnterpriseServices, поскольку это
снижает производительность.
Обзор разработки COM+-компонентов
Создание .NET-компонентов, способных к взаимодействию с сервисами
COM+, включает следующие этапы (табл. 2).
- Создание библиотеки классов.
- Определение всех классов как производных от
System.EnterpriseServices.ServicedComponents.
- Создание сборки.
- Создание строгого имени.
Табл. 2. Терминология, используемая при разработке
.NET-компонентов
Термин |
Описание |
Библиотека классов (class library) |
Проект DLL, содержащий классы. В общем случае
в проектах такого типа пользовательский интерфейс не
предусматривается. |
System.EnterpriseServices.ServicedComponents |
Класс .NET Framework, необходимый для
взаимодействия с сервисами COM+. |
Сборка (assembly) |
Описание всех классов и интерфейсов в
проекте. |
Строгое имя (strong name) |
Позволяет генерировать GUID из сборки, чтобы
ваш компонент мог регистрироваться в COM+ Services |
Разработка компонентов, поддерживающих транзакции
Ниже вы узнаете, как создаются .NET-компоненты, использующие
транзакционные сервисы COM+. Вы также научитесь писать компоненты и
взаимодействующие с ними клиентские приложения.
Создание COM+-компонента, поддерживающего транзакции
Чтобы получить .NET-компонент, работающий с сервисами COM+, нужно
выполнить ряд действий. Сначала вы должны создать класс, производный от
System.EnterpriseServices.ServicedComponent. Этот базовый класс
предоставляет вам все методы и свойства, необходимые для взаимодействия
с сервисами COM+. Далее пометьте класс как требующий новой транзакции, а
все его методы, создаваемые вами, - как способные автоматически
завершать транзакции в отсутствие ошибок. Попробуем сделать это на
практике.
- Запустите Microsoft Visual Studio® .NET и создайте новый проект
на основе шаблона ClassLibrary.
- Переименуйте файл Class1.vb в COMPlusServices.vb.
- Откройте COMPlusServices.vb и измените имя класса с Class1 на
COMPlusServices.
- Поместите в новый класс код, показанный ниже.
Imports System.EnterpriseServices
Imports System.Reflection
'********************************************
' Для регистрации в COM+
' Укажите имя COM+-приложения
<Assembly: ApplicationNameAttribute("ComPlusExample")>
' Укажите строгое имя сборки
<Assembly: _
AssemblyKeyFileAttribute("bin/ComPlusExample.snk")>
'********************************************
<TransactionAttribute(TransactionOption.Required)> _
Public Class COMPlusServices
Inherits ServicedComponent
Public Sub New()
MyBase.New()
End Sub
<AutoComplete()> Public Function DoTransaction() _
As String
Return "Success with COM+"
End Function
End Class
Сначала в этом коде импортируется пара пространств имен, чтобы
исключить ввод излишнего текста при объявлении компонентов.
Далее идет регистрация в COM+. Поместите в код следующую строку:
' Укажите имя COM+-приложения
<Assembly: ApplicationNameAttribute("ComPlusExample")>
В этой строке атрибуту ApplicationNameAttribute присваивается
значение ComPlusExample - это и будет именем COM+-приложения,
указываемым при регистрации в каталоге COM+. После первого вызова этого
компонента (когда вы откроете оснастку COM+ Applications в консоли MMC)
вы увидите заданное имя приложения.
Затем в коде объявляется атрибут AssemblyKeyFileAttribute:
<Assembly: _
AssemblyKeyFileAttribute("bin/ComPlusExample.snk")>
Он сообщает каталогу COM+, где находится информация о строгом имени
сборки. SNK-файл, описывающий компонент для COM+, мы создадим позже.
Наконец, в коде объявляется класс COMPlusServices:
<TransactionAttribute(TransactionOption.Required)> _
Public Public Class COMPlusServices
Атрибут перед именем класса сообщает COM+, что вы хотите установить
транзакционный атрибут в Required. То же самое можно сделать вручную
через оснастку COM+ Applications (рис. 1).
Следующая строка кода указывает, что данный класс наследуется от
класса ServicedComponent из пространства имен System.EnterpriseServices.
Inherits ServicedComponent
Без этого наш компонент не сможет работать в COM+.
Добавление транзакционного метода
Закончив настройку класса, можно написать какой-нибудь метод,
делающий реальную работу. Создадим функцию DoTransaction, которая
возвращает строковое значение и демонстрирует синтаксис методов,
необходимый для того, чтобы они могли участвовать в транзакциях.
<AutoComplete()> Public Function DoTransaction() As String
Return "Success with COM+"
End Function
Важно предварить метод атрибутом <AutoComplete()>. Этот атрибут
указывает, что если при выполнении метода не возникнет исключения, по
его завершении должен быть автоматически вызван SetComplete; в ином
случае исполняющая среда .NET должна сама вызвать SetAbort. Это
отличается от написания компонентов COM в Visual Basic 6.0, где
программисту приходилось явно вызывать метод SetComplete или SetAbort.
Создание строгого имени
Перед компиляцией компонента необходимо назначить его сборке строгое
имя. Без этого каталог COM+ не увидит ваш компонент и не сможет его
зарегистрировать. На самом деле вы уже сделали это через знакомый вам
атрибут AssemblyKeyFile, но теперь нужно создать само строгое имя и
связать GUID со сборкой при помощи утилиты Strong Name Tool (Sn.exe).
- Откройте окно командной строки.
- Чтобы создать строгое имя, наберите следующую команду и нажмите
Enter.
sn -k ComPlusExample.snk
- Скопируйте файл ComPlusExample.snk из корневого каталога
жесткого диска (скорее всего, это C:/) в каталог bin проекта (этот
каталог находится в каталоге вашего проекта).
Теперь скомпилируйте программу, чтобы создать файлы, необходимые для
регистрации компонента в каталоге COM+. Для этого в Visual Studio .NET
выберите из меню Build команду Build.
Создание тестового клиентского приложения
Теперь, когда компонент собран, осталось создать клиентское
приложение и протестировать этот компонент. Создайте простое консольное
приложение, в котором метод Main стартового модуля создает экземпляр
компонента и вызывает его метод DoTransaction(). Придерживайтесь
следующей схемы.
- В Visual Basic .NET создайте новое консольное приложение.
- Добавьте в него ссылку на только что созданный компонент.
- Поместите в приложение код, показанный ниже.
Module modMain
Sub Main()
Dim objCOMPlus As New _
COMPlusJumpStart.COMPlusServices()
Console.WriteLine(objCOMPlus.DoTransaction)
Console.ReadLine()
End Sub
End Module
Тестирование
Наконец, все готово для того, чтобы запустить приложение и
посмотреть, как оно работает.
- Откройте оснастку Component Services в консоли MMC и убедитесь,
что компонент динамически зарегистрирован в каталоге COM+ (окно
оснастки должно выглядеть примерно, как на рис. 2).
- Скомпилируйте и запустите консольное приложение.
Рис. 2. Новый сервисный .NET-компонент в каталоге COM+
Защита на основе ролей
Если COM-компоненты, работающие в COM+, вызываются множеством
пользователей, следите за тем, чтобы доступ к компонентам получали
только авторизованные пользователи. COM+ позволяет определять роли и
назначать их пользователям Windows NT. Назначив роли, определите, какие
компоненты (или даже их методы) доступны для этих ролей.
Добавим к классу COMPlusServices метод, который позволит ему
поддерживать модель защиты на основе ролей. Вы создадите роль Managers и
внесете в новый метод код, проверяющий, есть ли у вызывающего
пользователя эта роль.
Организация поддержки защиты на основе ролей
Чтобы создать новую роль безопасности, вместо прямой модификации
COM+-приложения через оснастку Component Services добавьте к проекту
новый атрибут. Мы добавим роль Managers с помощью класса
SecurityRoleAttribute. Его конструктор принимает два аргумента:
строковый role и булев everyone. Аргумент role задает имя создаваемой
роли, а everyone определяет, надо ли добавить встроенную группу Everyone
к пользователям этой роли.
- Добавьте к приложению COM+ новую роль безопасности, поместив
следующий код сразу после комментария "Регистрационные сведения
COM+":
'********************************************
' Регистрация в COM+
' Атрибут защиты на основе ролей
<Assembly: SecurityRoleAttribute("Managers", False)>
- Измените настройку уровня безопасности так, чтобы проверка
доступа выполнялась на уровнях процесса и компонента.
- Откройте оснастку COM+ Services.
- Перейдите на вкладку Security и измените уровень
безопасности, как показано на рис. 3.
Рис. 3. Установка свойства Security level в COM+ Catalog
Можно не делать все это вручную, а добавить к компоненту атрибут,
заставляющий его проверять права доступа на уровне компонента. Ниже
показан код, который следует добавить в раздел "Регистрация в COM+" в
начале класса COMPlusServices:
<Assembly: ApplicationAccessControlAttribute
(AccessChecksLevel:=AccessChecksLevelOption.ApplicationComponent)>
Проверка на принадлежность роли
А теперь добавим к классу новый метод - IsManager. Он будет
проверять, является ли пользователь членом роли Managers. Этот метод -
не что иное, как функция, возвращающая булево значение, которое
указывает, принадлежит ли пользователь к группе Managers. Чтобы получить
доступ к контексту защиты пользователя, вызывающего метод,
воспользуйтесь классом SecurityCallContext. Получить текущий контекст
вызывающего можно методом CurrrentCall. Далее вызовите метод
IsCallerInRole, указав Managers как имя роли.
- Добавьте в класс COMPlusServices показанный ниже метод:
Public Function IsManager() As Boolean
Dim objCallContext As SecurityCallContext = _
SecurityCallContext.CurrentCall
IsManager = _
objCallContext.IsCallerInRole("Managers")
End Function
Чтобы протестировать новый метод, наш компонент нужно
перекомпилировать.
- Для этого в Visual Studio .NET выберите в меню Build
команду Rebuild Solution.
Тестирование
- Модифицируйте код метода Sub Main() клиентского приложения, как
показано ниже:
Sub Main()
Dim objCOMPlus As New _
COMPlusJumpStart.COMPlusServices()
Console.WriteLine(objCOMPlus.DoTransaction)
Console.WriteLine(objCOMPlus.IsManager().ToString)
Console.ReadLine()
End Sub
- Запустите консольное приложение из командной строки, набрав в
ней имя скомпилированного исполняемого файла.
При первом запуске этого кода возникнет исключение с сообщением об
отклонении запроса на доступ, поскольку к роли Managers пока не
добавлено ни одного пользователя. Чтобы исправить это, добавьте себя к
роли Managers и запустите клиентское приложение еще раз. На этот раз
исключений быть не должно. В клиентское приложение также можно добавить
обработку исключений. Вот как оно будет выглядеть после добавления кода
для обработки исключений:
Sub Main()
Try
Dim objCOMPlus As New _
COMPlusJumpStart.COMPlusServices()
Console.WriteLine(objCOMPlus.DoTransaction)
Console.WriteLine(objCOMPlus.IsManager().ToString)
Console.ReadLine()
Catch objException As Exception
Console.WriteLine("An error occurred. " _
& "Details: " _
& objException.Message)
Console.ReadLine()
End Try
End Sub
Использование компонентов с поддержкой очередей
Добавить поддержку очередей в COM+-приложение несложно. Для этого
достаточно сделать его внешним сервером (out-of-process server) и задать
на вкладке Queuing свойства Queued и Listen. После этого клиентское
приложение сможет вызывать ваши компоненты как синхронно, так и
асинхронно. Изящество этой функции в том, что модифицировать код
COM-объекта не требуется - достаточно изменить его свойства в COM+
Catalog.
.NET Framework поддерживает компоненты с очередями (queued
components), и, как вы, наверное, догадываетесь, для организации
поддержки очередей в своих компонентах менять их свойства в каталоге
COM+ вручную не обязательно - можно воспользоваться соответствующими
атрибутами.
Добавим к классу COMPlusServices метод, который мы будем асинхронно
вызывать из клиентского .NET-приложения, используя сервисы COM+ Queued
Components.
- Сделайте свое COM+-приложение внешним сервером (обязательное
требование для работы с Queued Components). Чтобы сделать это через
атрибуты, добавьте к проекту следующий код:
'********************************************
' Регистрация в COM+
<Assembly: ApplicationActivationAttribute(ActivationOption.Server)>
- Теперь добавьте к компоненту поддержку очередей. Сделайте его
доступным для очередей MSMQ и заставьте его следить за собственной
очередью для обработки сообщений. Вот код, позволяющий сделать это
через атрибуты:
'********************************************
' Регистрация в COM+
<Assembly: ApplicationQueuingAttribute(Enabled:=True,
QueueListenerEnabled:=True)>
- Добавьте к классу метод QueueTest (как подпрограмму, поскольку
он не должен ничего возвращать). Пусть он записывает сообщение в
журнал приложений Windows (Windows Application Log). Вот код этого
метода:
Public Sub QueueTest()
System.Diagnostics.EventLog.WriteEntry(_
"COMPlusServces", "Queue Test", _
Diagnostics.EventLogEntryType.Error)
End Sub
Все. Для организации поддержки очередей в вашем компоненте больше
ничего не нужно.
Тестирование
Теперь попробуем протестировать компонент с поддержкой очередей. Для
этого придется создать другое консольное приложение, вызывающее данный
компонент.
- Создайте новое консольное приложение.
- Добавьте в его процедуру Sub Main следующий код:
Sub Main()
Dim objTest As COMPlusJumpStart.COMPlusServices
Dim strMoniker
strMoniker = _
"queue:/new:COMPlusJumpStart.COMPlusServices"
objTest = GetObject(strMoniker)
objTest.QueueTest()
End Sub
Этот код асинхронно вызывает метод QueueTest компонента. А для
синхронного вызова метода обращайтесь к нему так же, как вы делали это
при вызове любого другого метода компонента.
Теперь запустите консольное приложение и проверьте, как работает
компонент с очередями.
Что нового появилось в COM+ после Visual Basic 6.0?
Многое из того, что вы знали по Visual Basic 6.0 или COM, в .NET
осталось без изменений. Но теперь можно свести к минимуму усилия по
написанию кода и сопровождению программ, используя инфраструктуру .NET
Framework, которая упрощает взаимодействие между объектами.
Вот типичный пример подобного усовершенствования: в Visual Basic 6.0
программисту приходилось самому явно вызывать SetComplete или SetAbort,
а в .NET эти методы вызываются атрибутом <AutoComplete()>.
Другое отличие между Visual Basic .NET и Visual Basic 6.0 в том, что
компоненты Visual Basic 6.0 не могут работать с пулами объектов COM+,
поскольку используют модель потоков STA (Single Threaded Apartment).
Компоненты Visual Basic .NET, являясь .NET-компонентами, поддерживают
любые модели потоков и, следовательно, могут работать с пулами объектов
COM+.
Резюме
Как видите, .NET Framework позволяет легко использовать преимущества
сервисов COM+. Это значит, что вы можете добавлять новые .NET-компоненты
к существующим приложениям, написанным с использованием COM/COM+, и они
будут без проблем работать друг с другом. Это очень важно, так как дает
новую жизнь существующему коду, использующему COM и COM+. Если вы пишете
новое приложение "с нуля", настоятельно рекомендуем делать этот
исключительно с использованием .NET Framework, что намного эффективнее.
Об авторах
Тим Мак-Карти (Tim McCarthy) (MCSD, MCT) работает главным инженером в
InterKnowlogy, где занимается проектированием и разработкой
многоуровневых приложений с использованием последних технологий
Microsoft. Регулярно выступает на DevDays, недавно завершил подбор
материалов учебного курса по .NET для MSDN Field Content Team. Автор
ряда глав в нескольких книгах, вышедших в издательстве Wrox Press,
последняя из них - "Professional VB.NET"; пишет статью в рубрике
"Developer DotNET Update" журнала "SQL Server Magazine".
Пол Д. Шериф (Paul D. Sheriff)
- владелец PDSA, Inc., компании, занимающейся консалтингом и разработкой
заказного ПО. Эта компания расположена в Южной Калифорнии, где Пол
является региональным директором MSDN. Он автор книги "Paul Sheriff
Teaches Visual Basic", посвященной Visual Basic 6, а также 72 учебных
видеофильмов по Visual Basic, SQL Server, .NET и Web-разработке,
записанных для Keystone Learning Systems. Соавтор книги
ASP.NET Jumpstart. Более подробные сведения о PDSA, Inc. можно
получить, посетив Web-сайт www.pdsa.com.
О компании Informant Communications Group
Informant Communications Group, Inc. (www.informant.com)
- медиа-компания с разносторонними интересами в секторе информационных
технологий. Специализируется на выпуске изданий и каталогов, проведении
конференций и создании Web-сайтов, посвященных разработке ПО. Основанная
в 1990 году и имеющая отделения в США и Великобритании, ICG получила
признание как интегратор медийного и маркетингового контента, успешно
удовлетворяя растущую потребность IT-профессионалов в качественной
технической информации.
© 2002 Informant Communications Group и Microsoft
Corporation
Техническое редактирование выполнено PDSA, Inc.