Новые средства и документация для создания интегрированных настольных приложений
Автор: Кристиан Тилмани и Джим Кин
Источник:
здесь В последнее время огромное внимание привлечено к обеспечению сотрудников информационных отделов средствами бизнес-анализа (Business Intelligence, BI), которые помогают им принимать более обоснованные решения. Большинство корпоративных средств бизнес-анализа объединяет информацию из множества источников, используя, как правило, какую-либо разновидность интеграции данных на серверной стороне. Будь то система подготовки отчетов, суммирующая данные, средство поддержки коллективной работы вроде Microsoft SharePoint или собственное решение по интеграции корпоративных приложений (EAI), обеспечивающее управление бизнес-процессами, во главу угла всегда ставится своевременная доставка этой информации. А на ее использование обращают мало внимания.
В большинстве случаев для принятия решений сотрудник информационного отдела использует несколько приложений: Web-браузер для просмотра портала, приложение для доступа к EAI-решению и средство просмотра отчетов для чтения итоговых данных. Со временем этот сотрудник приобретает необходимые навыки, научившись вручную собирать и систематизировать данные от разных приложений. Обычно это делается запуском Microsoft Outlook, Word, Excel, Internet Explorer и множества внутренних нестандартных приложений, предоставляемых компанией. Данный способ интеграции, вынуждающий пользователя крутиться волчком на своем рабочем месте, имеет чудовищные недостатки: высокие затраты на обучение новых пользователей, неспособность системы предоставить нужную информацию нужным лицам в должном формате, появление ошибок в данных и т. д. Разве не эффективнее было бы реализовать надежную инфраструктуру интеграции и хостинга с моделью развертывания, которая упростила бы данный вид интеграции приложений?
Большинство разработчиков рассматривает архитектуры, ориентированные на сервисы (service-oriented architecture, SOA), как средство доставки информации, а не ее использования. Но как управлять всеми этими островками автоматизации? Вот здесь-то и возникает идея об интеграции настольной среды.
Как архитекторы информационных решений, мы стремимся сократить необъятный простор бизнес-приложений и улучшить рабочую среду пользователя. Но здесь одной из труднейших задач является создание такого решения, которое бесшовно интегрировало бы множество приложений, запущенных на настольном компьютере. Такие технологии, как DDE, OLE, COM, почтовые ящики (mailslots) и им подобные, предназначены для интеграции локальных приложений. В результате их применения получаются жестко сопряженные, ненадежные настольные приложения, которые обычно требуют больших расходов на внедрение и сопровождение.
Integrated Desktop - новейшая реализация архитектуры подключенных систем (connected systems architecture), предназначенной для настольных приложений. Integrated Desktop - это архитектура хостинга со слабым сопряжением и составной UI, запускаемый на настольном компьютере и поддерживаемый серверной стороной на основе архитектуры со слабым сопряжением. При этом сокращается количество приложений, с которыми пользователь должен иметь дело, и все помещается в один «флакон». Все технологии, необходимые для создания приложений Integrated Desktop, уже содержатся в .NET Framework. Однако до сих пор их интеграция представляла собой нелегкую задачу.
В основе стратегии Integrated Desktop лежит поддержка сервисов. В то время как архитектура сама по себе абсолютно не требует инфраструктуры сервисов, стратегия построения составных корпоративных настольных приложений - требует. Характер приложений Integrated Desktop, слабо зависимых друг от друга, естественен для SOA-систем. Сохранение качеств архитектуры со слабым сопряжением помогает развертыванию там, где эти разновидности архитектур часто натыкаются на препятствия.
Базовыми уровнями для Microsoft-реализации Integrated Desktop служат новые Composite UI Application Block (CAB) и Smart Client Software Factory. В связке друг с другом они становятся мощным инструментом для архитекторов решений, создающих собственную инфраструктуру клиентских приложений.
Базовая терминология
Прежде чем углубляться в технологию Integrated Desktop, разберемся в базовой терминологии.
CAB - Инфраструктура и документация, помогающие создавать сложные, слабо сопряженные смарт-клиенты, поддерживающие компоновку (composability) в период выполнения.
Context (контекст) - Относится к общим данным, совместно используемым множеством приложений. Данные контекста нужны для согласования информации между элементами, даже когда эти элементы содержатся в размещенных на хосте подприложениях внутри составного UI.
Dependency Injection - Проектировочный шаблон, реализованный в расчете на Object Builder для динамического включения объектов в составной UI в период выполнения. Это реализация проектировочного шаблона Мартина Фаулера (Martin Fowler), иногда называемая Inversion of Control.
Event Broker - Механизм взаимодействия между компонентами внутри смарт-клиента, который использует модель «издатель-подписчик», позволяющую любому элементу CAB взаимодействовать с другими элементами составного (композитного) UI.
Module (модуль) - Обозначает единицу развертывания (deployment unit) CAB-приложений. Модули содержатся в файлах сборок (DLL) и могут включать одно или несколько подприложений, которые будут задействованы в составном UI. Последний может загружать любое количество модулей.
Smart Client Software Factory - Интегрированный набор документации (демореализации, шаблоны, документы «how-to», пакеты Guidance Automation Toolkit, документация по архитектуре и примеры кода), которая вкупе с CAB и Enterprise Library делает возможной разработку сложных смарт-клиентов.
Smart Client Service - Сервис, выполняемый на клиентской стороне и предоставляющий базовую инфраструктуру для работы таких элементов смарт-клиента, как система защиты, средства развертывания, темы и т. д.
Smart Part (View) - Повторно используемый составной интерфейс, который отвечает за компонент представления в используемом CAB и Smart Client Software Factory шаблоне «модель-представление-контроллер» или «модель-представление-презентатор». (Smart Part просто поддерживает работу с Visual Studio. В большинстве случаев применимы пользовательские элементы управления.)
Theme (тема) - Отвечает за внешний вид GUI-элементов и настольного приложения в целом. Аналогична темам ASP.NET, но с учетом специфики смарт-клиентов. Для управления темами в Smart Client Software Factory используются рабочие пространства CAB или диспетчеры разметки (layout managers).
UI Elements (UI-элементы) - Интерфейсные элементы управления общего применения, используемые навигационными элементами в оболочке. В качестве примера можно привести элементы меню, панелей инструментов и пользовательские компоненты для поддержки навигации. UI-элементы можно связывать с командами и динамически контролировать из любого подприложения в период выполнения.
Work Item (рабочий элемент) - Контейнер CAB для хранения ссылок на CAB-компоненты, такие как элементы Smart Part, события, сервисы, общие данные, рабочие пространства, команды и другие рабочие элементы. Каждый рабочий элемент обычно поддерживает определенный набор свойств или же рассчитан на конкретный «случай применения» («use case») для какого-либо подприложения.
Как работает CAB
CAB представляет собой реализацию шаблонов и концепций, используемых при создании сложных клиентских смарт-приложений (смарт-клиентов). Проще говоря, это надстройка Windows Forms, помогающая в создании корпоративных настольных приложений.
Мы могли бы посвятить всю статью обсуждению CAB, а описание некоторых компонентов вообще в нее не поместилось. Поэтому мы сосредоточимся на основных компонентах CAB, но рекомендуем вам скачать прилагаемые к статье материалы и самостоятельно изучить их. Для начала посетите
сайт сообщества CAB (EN).
CAB разработан для поддержки многих сценариев применения, в том числе для OLTP-клиентов, клиентских порталов и приложений, используемых в информационных отделах. Благодаря модульности и нетребовательности к ресурсам CAB можно применять не только в корпоративных настольных приложениях, но и в небольших смарт-клиентах.
CAB позволяет распределять задачи разработки интерфейса смарт-клиента, четко разделяя этот интерфейс на части. В итоге CAB способствует повторному использованию кода и дает возможность легко реализовать такие концепции, как рабочий процесс внутри приложения (intra-application workflow). Чтобы обеспечить возможность повторного использования, составной UI, построенный на основе инфраструктуры CAB, разбивается на несколько работающих частей. Оболочка приложения выступает в роли хоста и загрузчика ваших элементов составного UI. Загруженные и выведенные на экран с помощью оболочки, UI-элементы предоставляют пользователю точки взаимодействия вроде меню и других навигационных компонентов. Сами по себе оболочки слабо связаны с составными частями приложения, что обеспечивает гибкость при проектировании UI. Оболочка и сервисы CAB «управляют автомобилем», но вам придется позаботиться о движке приложения или приложений, для которых оболочка будет служить хостом.
CAB не только предоставляет инфраструктуру для хостинга повторно используемых элементов, но и предлагает базовый набор сервисов смарт-клиента для таких задач, как загрузка модулей, обмен сообщениями, сохранение состояния и т. д. Все это можно реализовать в коде или через файл .config вашего приложения. К базовым сервисам относятся следующие.
Загрузчик модулей и сервисы перечисления модулей Сервисы на основе провайдеров; управляют перечислением и загрузкой модулей в настраиваемом каталоге.
Сервис Event Broker Передает сообщения между частями приложения и между подприложениями, размещаемыми в составном UI.
Сервис аутентификации Сервис на основе провайдеров; отвечает за проверку пользовательских учетных данных, доступ к сертификатам и взаимодействие с серверными провайдерами данных.
Сервис сохранения состояния Сервис хранилища на основе провайдеров; сохраняет состояние рабочих элементов для совместного использования контекстных данных и поддержки временной приостановки и последующей активизации рабочих элементов.
Чтобы реализовать движок CAB-приложения, обычно начинают с создания CAB-модуля. Модули предоставляют точку входа для вашего индивидуального набора средств, который иногда называют размещенным приложением (hosted application). Модули содержатся внутри собственных DLL-файлов и загружаются из оболочки в период выполнения. Доступность модулей и их загрузка полностью настраиваются и поддерживаются расширяемым каталогом программ. Если у вас есть опыт работы с Microsoft Enterprise Library, вы обнаружите, что в CAB применяется та же модель провайдеров. Модули не требуют прямых ссылок на них из проекта оболочки в Visual Studio и непосредственной привязки к исполняемому файлу. Они загружаются в период выполнения загрузчиком модулей.
Внутрь сборки модуля вы включаете рабочие элементы, представления, контроллеры и данные, которые необходимы, чтобы управлять набором средств с помощью CAB и типов Smart Client Software Factory, таких как Presenter, SmartPart и State. Эти три элемента, в частности, образуют шаблон MVP/MVC (Model-View-Presenter/Model-View-Controller), на котором базируются CAB-приложения. Сервисы подключаются по мере необходимости в соответствии с логикой приложения. Это позволяет разработчику динамически создавать новые экземпляры объектов или возвращать объекты, уже созданные внутри контейнера. Для CAB этот контейнер является рабочим элементом и одним из первых создается разработчиком модуля. Компоненты CAB, например клиентские сервисы и рабочие пространства, можно добавлять в контейнер явно с помощью AddNew:
_rootWorkItem.WorkItems.AddNew<WorkItemA>();
То же самое можно сделать через конфигурационный файл или декларативно:
[CreateNew]
public ShipNewOrderViewPresenter Presenter
{
set
{
_presenter = value;
_presenter.View = this;
}
}Внутри области видимости контейнера (рабочего элемента) эти компоненты можно при необходимости декларативно разыменовывать. Это обеспечивает слабое сопряжение, что делает доступными (позволяет добавлять) любые содержащиеся в контейнере элементы, управляемые CAB, как показано ниже:
[ServiceDependency]
public WorkItem WorkItem
{
set { _workItem = value; }
}Ключевой компонент CAB - Object Builder (также используемый новой версией Enterprise Library). С помощью Object Builder (благодаря поддержке концепции Dependency Injection) теперь можно создавать новые объекты какого-либо класса или возвращать существующие, если они подходят; выбирать определенный конструктор, если в классе их несколько; сопоставлять свойства и методы с атрибутами, которые будут влиять на создание и именование нового объекта; удобно удалять параметры из существующих объектов, двигаясь обратно по цепочке операций.
Object Builder представляет собой низкоуровневую утилиту, с которой вы вряд ли будете работать напрямую. Но знание концепции Dependency Injection является ключевым для понимания того, как сервисы включаются в ваш модуль. Это знание также окажет вам неоценимую помощь при отладке. Подробнее о Dependency Injection и прочих шаблонах, используемых в CAB, см. в документации по CAB.
При желании модуль можно разбить на части произвольным образом. В каждом модуле должен содержаться минимум один рабочий элемент, служащий драйвером этого модуля. Рабочие элементы, подобно любому приложению или подприложению, могут быть как очень простыми, так и очень сложными. Для CAB-приложения характерен следующий порядок работы:
- Пользователь дважды щелкает EXE-файл, отображающий оболочку.
- Оболочка появляется на рабочем столе, загружает заданные CAB-сервисы, отображает UI-элементы и загружает все сконфигурированные модули.
- По окончании загрузки каждый модуль добавляет по рабочему элементу в свой родительский элемент, чтобы управлять подприложением и выдавать запросы к рабочему элементу на показ его содержимого в поддерживаемом рабочем пространстве.
- Когда пользователь выбирает какой-либо элемент меню, срабатывает соответствующая команда.
- Обработчик команд реагирует на эту команду созданием дочернего рабочего элемента, который управляет другим подприложением и отображает его представления.
- Рабочий элемент отображает свое представление с помощью Smart Part.
- Пользователь взаимодействует с этим интерфейсом, который в свою очередь обращается к контроллеру (или его презентатору).
- Контроллер изменяет общие данные (состояние) и связывается с хостом, используя Event Broker.
- Event Broker отправляет актуальную информацию (контекст) другим модулям или компонентам.
CAB-модули могут быть самодостаточными или входить в более крупный набор модулей, размещенных в оболочке. Преимущества гибкости и архитектуры CAB по-настоящему проявляются в многомодульных смарт-клиентах. Гибкость заключается в первую очередь в том, что вам никогда не придется прямо ссылаться на свои сборки с модулями в проекте загружающей их оболочки, поскольку их будет загружать CAB в период выполнения. Кроме того, взаимодействовать друг с другом могут не только отдельные части одного модуля, но и части, запущенные во внешних модулях, которые содержатся внутри собственных сборок.
Создание простого CAB-приложения
Теперь создадим одномодульное приложение. Сначала я объясню в общих чертах, как создается простой смарт-клиент. (Позже в этой статье я рассмотрю более сложное интегрированное настольное приложение.)
У большинства интегрированных настольных приложений есть видимая, загружаемая при старте форма. Поэтому вы начинаете с оболочки Windows Forms, наследуете свой класс от FormShellApplication, создаете его экземпляр и вызываете его метод Run из метода Main своего приложения. Это приводит к запуску CAB-приложения и загрузке всех сконфигурированных сервисов, которые мы обсуждали ранее. Следующий шаг заключается в перегрузке методов из состава FormShellApplication, таких как AfterShellCreated, с целью заполнить меню и показать все видимые представления. (Можно также задействовать элементы Smart Part, которые попросту являются пользовательскими элементами управления, дополненными SmartPartAttribute.)
Чтобы при реализации AfterShellCreated инициализировать UI, вы регистрируете так называемый узел расширения (extension site), к которому будет обращаться CAB. Тем самым вы задаете диспетчер UI-элементов, и любой модуль сможет впоследствии добавлять дочерние UI-элементы (например, меню или панели инструментов) в любую точку любого модуля. Наконец, вы выводите на экран свои представления либо при загрузке оболочки, либо в ответ на команды UI-элементов, добавляемые при инициализации. Этими командами запускаются обработчики, благодаря которым ваш код может отвечать на любые команды, инициируемые любым традиционным UI-элементом в период выполнения. Это аналогично добавлению обычных обработчиков событий, но в более абстрактной форме.
Представления можно отображать через классы SmartPartPlaceHolder или в зависимости от того, какой CAB вызывает рабочее пространство. Этим попросту задаются контейнеры разметки, используемые для вывода ваших представлений в заданном порядке. Если вы когда-нибудь работали в Java со средствами абстрактных окон (abstract windows toolkit, AWT), эта концепция покажется вам знакомой.
Наконец, чтобы создать оболочку, зарегистрируйте интерфейс и отобразите Smart Part. Чтобы задействовать реальную мощь CAB, вы используете модули для инкапсуляции частей приложения в отдельные сборки. Это дает вам абстракции на этапе разработки, подобные COM-абстракциям периода выполнения, но без лишней сложности.
С помощью модулей вы можете включать в приложения независимые наборы средств, которые распространяются в собственных сборках. То есть компания может создавать новые версии модулей и распространять их, не мешая работе приложения Integrated Desktop. Файлы сборок с модулями, на которые нет прямых ссылок в EXE-файле, загружаются в период выполнения с помощью загрузчика модулей и сервисов перечисления. Каталог профиля CAB и конфигурационный файл приложения позволяют указывать, какие модули следует загружать, развертывать и запускать в оболочке.
Поставляемый вместе с CAB пример «Bank Teller» из раздела Quick Start является готовым одномодульным CAB-приложением. Он дает представление обо всех ключевых компонентах, о которых я здесь упоминал.
Конечно, создание реального корпоративного приложения Integrated Desktop требует гораздо больше простого UI с набором элементов управления. Вам придется решить массу проблем, в частности, как согласовывать доступ модулей к совместно используемой информации, как интегрировать в приложение Integrated Desktop программы, не относящиеся к CAB, и как управлять расположением элементов интерфейса.
Создание простого смарт-клиента: пошаговое руководство
- Создайте новое приложение Windows Forms.
- Добавьте в проект следующие ссылки на сборки:
Microsoft.Practices.CompositeUI
Microsoft.Practices.CompositeUI.WinForms
Microsoft.Practices.ObjectBuilder
- Создайте класс приложения, в котором определялось бы использование WorkItem (по умолчанию RootWorkItem) и вывод на экран формы Windows Forms. Чтобы создать класс MyWorkItem, сделайте его производным от CAB-класса WorkItem:
public class MyFirstCABApplication :
FormShellApplication<MyWorkItem, MyCABShellForm>
{
}
- Реализуйте метод Main своего приложения, создайте экземпляр приложения и вызовите Run:
[STAThread]
public static void Main()
{
new MyFirstCABApplication.Run();
}
- Перегрузите AfterShellCreated, вызовите его базовую реализацию и инициализируйте интерфейс:
protected override void AfterShellCreated()
{
base.AfterShellCreated();
ToolStripMenuItem fileItem = (ToolStripMenuItem)
Shell.MainMenuStrip.Items["File"];
MyWorkItem.UIExtensionSites.RegisterSite(
"File", fileItem.DropDownItems);
ToolStripMenuItem item =
new ToolStripMenuItem("Show Customer");
MyWorkItem.UIExtensionSites["File"].Add(item);
MyWorkItem.Commands["ShowCustomer"].AddInvoker(
item, "Click");
}
- Создайте Smart Part. Для этого введите в проект пользовательский элемент управления и добавьте ссылку на пространство имен Microsoft.Practices.CompositeUI.SmartParts. Затем добавьте в свой класс атрибут SmartPart:
[SmartPart]
public partial class CustomerSmartPart : UserControl
{
...
}
- Добавьте обработчик команд и отобразите Smart Part с помощью DeckWorkspace:
[CommandHandler("ShowCustomer")]
public void ShowCustomer(object sender, EventArgs e)
{
Form1 mainForm = new Form1();
CustomerSmartPart sp =
MyWorkItem.Items.AddNew<CustomerSmartPart>();
mainForm.deckWorkspace1.Show(sp);
}
В окно инструментария (toolbox) можно добавить любое рабочее пространство CAB и перенести его на проектируемую форму подобно обычному элементу управления.
Создание модуля и его инициализатора
- Создайте библиотеку классов или библиотеку элементов управления.
- Добавьте ссылки:
Microsoft.Practices.CompositeUI
Microsoft.Practices.ObjectBuilder
- Добавьте в проект ModuleAttribute, чтобы другие модули могли идентифицировать этот модуль в коде.
- Добавьте в свой файл AssemblyInfo.cs:
[assembly: Microsoft.Practices.CompositeUI.Module("MyFirstModule")]
- Создайте в проекте новый открытый класс и унаследуйте его от Microsoft.Practices.CompositeUI.ModuleInit. Перегрузите AddServices, чтобы добавлять CAB-сервисы в период выполнения, и перегрузите Load для отображения любого UI.
- Чтобы ваш модуль мог загружаться в период выполнения, создайте XML-файл ProfileCatalog.xml, который ссылается на ваш новый DLL-файл с модулем. Добавьте этот XML-файл в основной EXE-проект (оболочку, которую мы только что создали).
- Типичный каталог профиля выглядит так:
<?xml version="1.0" encoding="utf-8" ?>
<SolutionProfile
xmlns="http://schemas.microsoft.com/P&P/cab-profile">
<Modules>
<ModuleInfo AssemblyFile="Mod1.dll"/>
<ModuleInfo AssemblyFile="Mod2.dll"/>
</Modules>
</SolutionProfile>
Если хотите, можете подключить собственный сервис, чтобы использовать предпочитаемый вами формат каталога профиля. - Добавьте метод Load и реализуйте его в своем новом классе ModuleInit. В показанном ниже коде создается объект WorkItem вашего модуля с использованием метода AddNew в контексте RootWorkItem. Затем вызывается метод Run нового объекта WorkItem. Вы получаете рабочее пространство по имени и передаете это рабочее пространство методу Run. В данном примере целевым является пространство DeckWorkspace с именем deckWorkspace1:
public override void Load()
{
base.Load();
MyWorkItem myWorkItem =
RootWorkItem.WorkItems.AddNew<MyWorkItem>();
myWorkItem.Run(parentWorkItem.Workspaces["deckWorkspace1"]);
}
- Чтобы запустить свой код в ответ на запуск WorkItem, реализуйте метод Run своего класса MyWorkItem, как показано здесь:
public void Run(IWorkspace deckWorkspace)
{
IMyView view = this.Items.AddNew<MyView>();
deckWorkspace.Show(view);
}
Введение в Smart Client Software Factory
Помимо базовых сервисов CAB существует еще один класс фундаментальных сервисов, которые понадобятся вам при создании реального корпоративного приложения. Эти сервисы включают средства, помогающие управлять интегрированным настольным приложением (Integrated Desktop) в таких областях, как развертывание, защита и инициализация. Вам также могут потребоваться сервисы для ведения журналов, контроля производительности, настройки и кэширования, что позволит гарантировать корректную работу всех модулей в среде со слабым сопряжением.
Здесь вам поможет Smart Client Software Factory. Будучи не просто набором инструментов, Smart Client Software Factory содержит начальный комплект базовых сервисов смарт-клиента, упрощающих создание корпоративных интегрированных настольных приложений.
Все сервисы можно считать необязательными (опциональными) и в то же время расширяемыми. Smart Client Software Factory опирается на CAB и Enterprise Library и использует преимущества существующих блоков приложений. На рис. 1 показана архитектура сервисов смарт-клиента, основанная на Smart Client Software Factory.

Рис. 1. Сервисы смарт-клиента
Поскольку большинству компаний нужны сервисы общего применения, Microsoft встроила в Smart Client Software Factory соответствующий набор. Важное место в нем занимают две эталонные реализации, демонстрирующие типичное применение сервисов, содержащихся в Smart Client Software Factory. Первая реализация имитирует настольное приложение для эксперта по займам и содержит средства для работы в автономном режиме, уведомления конечного пользователя и подобные им функции. Вторая реализация имитирует настольное приложение для менеджера банка (многомодульная версия примера Bank Teller), демонстрируя применение сервисов защиты, развертывания и поддержки тем.
Комплекты руководств также оказывают ощутимую помощь при создании корпоративных приложений. Они включают относительно новый пакет Guidance Automation Toolkit (GAT) - расширение для Visual Studio 2005. С помощью GAT разработчики в группе могут создавать начальные наборы (или SDK), чтобы другие разработчики впоследствии могли добавлять в них модули и прочие элементы интегрированного настольного приложения. В Smart Client Software Factory входит Visual Studio Guidance Package for Smart Client Development. Это интегрированный набор инструментов, шаблонов, исходного кода и подробных инструкций, помогающих разработчикам интегрированного настольного приложения. Узнать более подробную информацию о GAT и скачать его можно по ссылке
msdn.microsoft.com/vstudio/teamsystem/Workshop/gat/default.aspx (EN).
Основные сервисы смарт-клиента
Integrated Desktop опирается на Smart Client Software Factory и CAB. Он может принимать форму универсального набора CAB-расширений, реализаций Smart Client Software Factory, базовых сервисов общего применения и библиотек, которые могут быть целиком или частично включены в любое приложение с составным UI.
Сервисы контекста - Один из важнейших элементов в создании интегрированного настольного приложения. И, по-видимому, один из зачастую неверно трактуемых. При работе с CAB-приложениями, содержащими несколько модулей, вы обычно сталкиваетесь с какой-либо формой совместного использования информации. Например, ваше приложение может содержать оболочку, модуль для вывода на экран информации о заказчиках, модуль для отображения строки сводных данных, модуль для поиска и другие специализированные модули. Каждый из этих модулей можно разрабатывать, внедрять и поддерживать независимо от других. CAB предоставляет инфраструктуру для этого, т. е. отвечает на вопрос «как». Но еще остается вопрос «что», т. е. информация, которая будет совместно использоваться этими модулями. Это может быть просто идентификатор заказчика. Event Broker уведомляет всех, что этот контекст изменился, благодаря чему все модули отображают надлежащую информацию в надлежащее время. Широковещательная рассылка идентификатора заказчика означает, что это совместно используемая информация, а значит, идентификатор заказчика относится к «контексту».
Сервисы контекста применяются исключительно для широковещательной рассылки и получения общей информации по аналогии с правилами системной политики, определенными для корпоративного настольного приложения. Вы должны установить базовый набор типов контекста и соответствующие контракты схем до включения какого-либо иного сервиса в свое интегрированное настольное приложение. То есть действовать так, как принято при проектировании в рамках архитектуры SOA: первым делом - контракт. Но вместо контрактов, определяемых в конечных точках Web-сервисов, вы определяете те же контракты между частями приложения Integrated Desktop. Фактически вы решаете такие же задачи, как и в проекте EAI или SOA.
Сервисы развертывания - Поддерживают разделение приложения Integrated Desktop на части, гарантируя, что отдельные модули можно будет загружать в период выполнения. Как вариант, сервисы развертывания можно создать на базе ClickOnce API. Эти сервисы должны обеспечивать на серверной стороне контроль за дополнительными модулями, которые предназначены для загрузки в приложение Integrated Desktop. Когда оболочка загружается, сервисы аутентификации подтверждают сервисам развертывания, что данные модули доступны для данного пользователя и потому должны быть загружены в приложение, если их там еще нет. Модули скачиваются, загружаются загрузчиком модулей и отображаются пользователю по мере необходимости. CAB позволяет добавлять роли пользователя в каталог профиля и вызывает загрузчик только для модулей, которые авторизованы на запуск с ролями, назначенными в текущий момент данному участнику системы безопасности (principal).
Сервисы защиты - В отличие от сервисов контекста сервисы защиты довольно просты для понимания. Их можно надстраивать над сервисами аутентификации, которые уже есть в CAB. Это создает отправную точку для применения пользовательских сервисов аутентификации и позволяет единообразно реализовать логику авторизации в приложении Integrated Desktop. С помощью сервисов и руководств из состава CAB и Smart Client Software Factory вы можете добавлять роли в отдельные модули, указывая тем самым, что эти модули связаны с определенными ролями. То есть вы можете задавать, какие модули загружать в зависимости от роли пользователя, вошедшего в систему, а также получаете ряд других средств контроля за тем, какие модули в данный момент загружены в приложение Integrated Desktop.
Сервисы интеграции - Развертывание единого корпоративного приложения Integrated Desktop было бы не очень продуктивным, если бы управляемые приложения Windows Forms оставались единственными кандидатами на интеграцию в смарт-клиенте. Обычно в организации есть какое-то количество ранее созданных (устаревших) приложений, которые надо интегрировать так, чтобы они могли оставаться автономными и вместе с тем участвовать в задачах, выполняемых приложением Integrated Desktop. Сюда входят Web-приложения, созданные без применения .NET, Web-сервисы ASP.NET, COM- и даже консольные приложения.
Сервисы интеграции в Smart Client Software Factory помогают решать некоторые из этих задач в вашем интегрированном настольном приложении. В статье рассматривается интеграция одного типа устаревших приложений - Web-приложений. Мы покажем, как CAB и Smart Client Software Factory (вместе с соответствующими комплектами руководств) помогают с минимальными усилиями создать Web-модуль для хостинга любого Web-приложения.
Функциональные уровни Integrated Desktop
Integrated Desktop состоит из трех уровней: базисного, платформы и прикладного. Важно понимать эти уровни и то, как они соотносятся с архитектурой интегрированного настольного приложения при его разработке. На рис. 2 показана связь этих уровней с различными уровнями архитектуры Integrated Desktop.

Рис. 2. Архитектура Integrated Desktop
Базисный уровень - Здесь содержатся все базовые клиентские сервисы CAB, а также сервисы, подобные сервисам защиты и развертывания, которые могут быть дополнены любым модулем или элементом Smart Part. Здесь же представлены объединенные горизонтальными связями компоненты интегрированного настольного приложения. CAB и Smart Client Software Factory занимают значительную часть базисного уровня. Этот уровень и соответствующие ему клиентские сервисы необходимы в первую очередь при создании инфраструктуры интегрированного настольного приложения.
Уровень платформы - На этом уровне размещаются сервисы, предоставляющие элементы, специфичные для платформ или технологий, например сервисы для поддержки устаревших приложений. Данный уровень состоит из компонентов, которые разработчик модулей или элементов Smart Part может использовать, чтобы включать в приложение элементы, зависимые от соответствующей платформы. Если у вас несколько Web-приложений, которые нужно интегрировать в приложение Integrated Desktop, их хостинг упростят универсальные сервисы поддержки клиентских Web-приложений, которые являются одним из компонентов вашей IDF. Например, вы хотите воспользоваться имеющимся у вас приложением, которое управляет корзиной покупателя и уже находится в эксплуатации. Сервисы уровня платформы помогут хостингу этого приложения в вашем интегрированном решении так, что это приложение будет работать подобно любому другому управляемому модулю. Smart Client Software Factory обеспечивает набор сервисов этого уровня для поддержки устаревших приложений.
Прикладной уровень - Включает только приложения и повторно используемые клиентские бизнес-функции. Предоставляет клиентские сервисы, специфичные для бизнеса. Состоит из модулей, с которыми вы обычно взаимодействуете, - для поиска, получения информации о заказчике, поддержки корзины покупателя.
Интеграция устаревших Web-приложений
Хостинг в CAB-приложении существующего Web-приложения требует нечто большего, чем просто добавления в Smart Part элемента управления, представляющего браузер. Смысл интеграции на клиентской стороне в том, чтобы все приложения (или модули) были полностью интегрированы. Иначе говоря, они должны взаимодействовать и обмениваться информацией в обоих направлениях. Это было возможно и до появления CAB, но решения получались громоздкими и не универсальными.
Как уже говорилось, теперь можно создать Web-модуль и использовать его для хостинга любого Web-приложения. Это никак не отразится на работе других модулей. Сейчас мы пошагово разберем процесс построения простого Web-модуля (подобного показанному на рис. 3), опираясь на руководство, предложенное командой разработчиков Smart Client Software Factory. Мы воспользуемся сервисами CAB и новыми пакетами Guidance из состава Smart Client Software Factory.

Рис. 3. Web-приложение, хостинг которого осуществляется на основе Web-модуля
Первое, что надо сделать, - создать новое Web-приложение или расширить существующее. В этом примере описываются этапы создания нового Web-приложения ASP.NET. Вы можете взять его за образец и при модификации существующих Web-приложений. Описанный процесс несколько трудоемок: вы должны добавить в приложение JScript и использовать его объектную модель для взаимодействия с Web-приложением.
Создав пример Web-страницы, которая будет вести себя как типичное Web-приложение, мы займемся построением Web-модуля. Но сначала вы должны скачать следующие ресурсы:
- Guidance Automation Extensions (GAX);
- пакет руководств Composite UI Application (убедитесь, что это свежая версия);
- Composite UI Application Block;
- простое приложение-оболочку с надлежащими ссылками на библиотеку CAB и Smart Client Software Factory;
- библиотечный проект со всем общим кодом, который можно использовать в других модулях и библиотеках приложений.
Будучи частью Smart Client Software Factory, классы вроде Microsoft.Practices.SmartClient.Web.WebPresenter и Microsoft.Practices.SmartClient.Web.WebView предоставляют базовые средства для автоматической диспетчеризации с помощью Event Broker из состава CAB тех событий, которые генерируются вашей Web-страницей. Это позволяет оснастить любой Web-модуль встроенным в CAB механизмом коммуникаций по умолчанию, через который будут автоматически передаваться в обе стороны все события Web-страницы. Класс Microsoft.Practices.SmartClient.Web.WebView наследует от элемента управления «браузер» и может повторно использоваться в вашем Web-модуле.
Заметьте, что пакет руководств не обязателен, он лишь добавляет в ваш проект несколько шаблонов кода, например сервисы, предоставляемые Smart Client Software Factory. В качестве альтернативы можете скачать примеры Web-страницы и Web-модуля, прилагаемые к этой статье.
Этап 1: создание Web-страницы
Начнем с создания Web-страницы, которая будет работать в качестве устаревшего Web-приложения.
- Создайте новый Web-проект или добавьте новую страницу в существующий Web-проект.
- При желании можете добавить ссылку на любую библиотеку общего назначения, содержащую, например, какие-нибудь константы, которые будут использоваться Web-приложением.
- Добавьте HTML-кнопку, свойству Text которой присвойте значение «Fire Context Changed Event (from JavaScript)».
- Добавьте ASP.NET-кнопку, свойству Text которой присвойте значение «Fire Context Changed Event (from ASP.NET server)».
- Добавьте текстовое поле HTML с идентификатором «txtCustomerName».
- Добавьте следующий код в метод Page_Load этой страницы (необходим только при использовании серверных элементов управления ASP.NET):
ClientScript.RegisterOnSubmitStatement(cstype,
Common.Events.ContextChanged,
BuildRaiseEvent(Common.Events.ContextChanged));
- Добавьте следующий закрытый метод (он тоже нужен лишь при использовании серверных элементов управления ASP.NET):
private string BuildRaiseEvent(string topic)
{
StringBuilder sb = new StringBuilder();
sb.Append("window.external.FireEvent(\\"");
sb.Append(topic);
sb.Append("\\",0);");
return sb.ToString();
}
- Дважды щелкните первую кнопку и добавьте код для события onclick:
window.external.FireEvent("ContextChangedEvent","Param1");
Этот код отправляет событие Web-страницы посредством Smart Client Software Factory в код Web-браузера и в смарт-клиент, использующий Event Broker. - Добавьте следующий код после обработчика события onclick из предыдущего пункта:
function EventBroker_Subscribe()
{
window.external.SubscribeEvent("ContextChangedEvent");
window.external.SubscribeEvent(
"CustomerContextChangedEvent");
}
function EventBroker_ContextChangedEvent()
{
window.alert("Context changed event: Hello from Web App");
}
Обработчик события Subscribe позволяет смарт-клиенту сообщить Web-странице, когда она должна подписаться на получение событий (обычно после того, как Web-страница загрузится в элемент управления «браузер»). Web-страница в свою очередь посылает ответ хосту и вызывает SubscribeEvent (событие, на которое подписывается web-страница). Это позволяет передавать все глобальные события CAB по мере их поступления от смарт-клиента в Web-страницу. А их перехват осуществляется обработчиками событий EventBroker_XXX в JScript. - Добавьте следующую JScript-функцию:
function EventBroker_CustomerContextChangedEvent(eventData)
{
document.getElementById('txtCustomerName').value =
eventData.Name;
}
Здесь показано, как передать данные события от смарт-клиента в Web-страницу и использовать в ней эти данные.
Этап 2: создание Web-модуля
Чтобы создать Web-модуль, сначала щелкните правой кнопкой мыши свое решение и выберите Add | CompositeUI | Module. В диалоговом окне Add New Project задайте имя своего модуля. Нажмите OK, выберите проект Shell и нажмите Finish.
Вы увидите, что появилось несколько новых элементов. В решение добавлен новый проект Web-модуля. Также добавлены необходимые ссылки, включая ссылки на библиотеки CAB и Smart Client Software Factory. Внутри иерархии каталогов нового проекта создана папка WorkItems, а в проекте созданы файл ModuleInit.cs и соответствующий класс.
Этап 3: создание нового рабочего элемента
Создать новый рабочий элемент так же легко. Щелкните правой кнопкой мыши папку WorkItems в модуле, который вы только что создали, и выберите Add | CompositeUI | WorkItem. Измените имя на WebWorkItem.cs. Выберите проект Shell и нажмите кнопку Finish.
После этого вы обнаружите, что создан файлы WebWorkItem.cs и соответствующий класс. Кроме того, для CAB и Smart Client Software Factory добавлены директивы using и необходимые ссылки.
В метод Load класса ModuleInit добавьте такой код:
WorkItemCatalog.RegisterWorkItem<WebWorkItem>();
В начало файла ModuleInit.cs вставьте директиву using:
using WebModule.WorkItems.WebWorkItem;
Этап 4: создание нового представления View
Этот этап касается обмена данными между Web-страницей и смарт-клиентом (в данном случае - Web-модулем).
- Щелкните правой кнопкой мыши папку WebWorkItem.
- Выберите Add | CompositeUI | View.
- Измените имя на WebView и нажмите кнопку Finish. Тем самым вы создаете интерфейс IWebView, класс WebPresenter и пользовательский элемент управления WebView. Здесь реализуется типичный шаблон MVP, применяемый в Smart Client Software Factory.
- Перейдите к классу WebWorkItem и добавьте код:
public void ShowInView(IShellView view)
{
WebView webView = this.Items.AddNew<WebView>();
view.MainWorkspace.Show(webView);
}
Тем самым вы добавляете WebView (элемент Smart Part) в набор элементов из набора рабочих элементов Smart Part и отображаете его, когда запускается рабочий элемент. - В режиме дизайнера откройте WebView UserControl.
- Добавьте элемент управления Microsoft.Practices.SmartClient.Web.WebView из Smart Client Software Factory.
- Установите свойство Url элемента управления Microsoft.Practices.SmartClient.Web.WebView так, чтобы оно указывало на только что созданную тестовую Web-страницу.
- Перейдите к файлу WebWorkItem.cs и добавьте директиву using:
using Microsoft.Practices.SmartClient.UI.Themes;
- Откройте класс WebPresenter и введите код:
[EventSubscription(Common.Events.ContextChanged,
Thread=ThreadOption.UserInterface)]
public void OnContextChange(object sender, EventArgs e)
{
System.Windows.Forms.MessageBox.Show( _
"Context changed: Hello from Rich UI component");
}
Это событие генерируется Web-страницей при посредстве CAB Event Broker и направляется в ваш код WebView. - Добавьте директиву using:
using Microsoft.Practices.CompositeUI.EventBroker;
- Откройте интерфейс IWebView и добавьте следующий код:
event WebBrowserDocumentCompletedEventHandler
DocumentCompleted;
- Откройте класс WebPresenter и добавьте код, показанный в листинге 1. Это позволяет Smart Client Software Factory реализовать подписку в ответ на загрузку Web-страницы. Когда Web-страница загружена, генерируется событие CustomerContextChangedForWebPage. С помощью Event Broker оно отправляется Web-странице в виде CustomerContextChanged (в JavaScript). В этом заключается передача контекста или информации от смарт-клиента в Web-страницу при загрузке Web-модуля из смарт-клиента, и это позволяет любому Web-приложению отображать информацию от смарт-клиента в ответ на свою загрузку. Заметьте, что у процесса-отправителя нет нужды в перегрузке функций - требуется лишь установить определенное событие при его загрузке.
Листинг 1. Реализация подписки
[EventPublication(Common.Events.CustomerContextChanged,
PublicationScope.Global)]
public event EventHandler<DataEventArgs<IIdentity>>
CustomerContextChangedForWebPage;
protected override void OnViewAdded()
{
this.View.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler(
OnDocumentCompleted);
}
protected override void OnViewRemoved()
{
this.View.DocumentCompleted -=
new WebBrowserDocumentCompletedEventHandler(
OnDocumentCompleted);
}
private void OnDocumentCompleted(
object sender, WebBrowserDocumentCompletedEventArgs args)
{
if (CustomerContextChangedForWebPage != null)
{
CustomerContextChangedForWebPage(this,
new DataEventArgs<IIdentity>(
Thread.CurrentPrincipal.Identity));
}
}
- Добавьте следующие директивы using:
using System.Threading;
using System.Security.Principal;
using Microsoft.Practices.CompositeUI.Utility;
- В класс WebView (реализация интерфейса IWebView) введите код:
public event WebBrowserDocumentCompletedEventHandler
DocumentCompleted
{
add { this.webView1.DocumentCompleted += value; }
remove { this.webView1.DocumentCompleted -= value; }
}
Этап 5: компиляция и тестирование решения
Разместите WebModule.dll в одном каталоге с приложением оболочки и добавьте модуль в ProfileCatalog.xml, чтобы его мог загружать сервис загрузчика модулей CAB.
Наконец, воспользуйтесь тем же шаблоном, по которому вы передаете сообщения другим модулям через Event Broker. Запустите этот Web-модуль так же, как и любой другой Web-модуль. Теперь все глобальные события будут передаваться от смарт-клиента в этот Web-модуль и обратно.
Взгляд в будущее
В моем примере маленький блок JavaScript-кода взаимодействовал с хост-приложением через Document Object Model (DOM). Этот способ применяется в InfoPath, чтобы Action Pane, основанный на HTML, мог получить доступ к DOM для XML-документа.
Для существующих приложений, базирующихся на Web-технологиях, это относительно грубый подход. Он требует внесения изменений в Web-приложение, его перекомпиляции и новой установки. Мы представляем менее грубый способ, который позволяет любому элементу Smart Part внедрять весь необходимый интегрирующий код в модель DOM HTML-страницы в период выполнения, а не при компиляции. Конечно, при этом нужно уделять должное внимание безопасности. А функциональность Event Broker из состава Smart Client Software Factory следует расширить методами связывания контекста смарт-клиента с элементами HTML-страницы.
У модулей для корпоративного применения захватывающие перспективы. Представьте себе основанный на Windows Workflow Foundation модуль рабочего процесса, который обеспечивает полностью хостинговую архитектуру в настольном приложении. Рабочий процесс интегрируется непосредственно в существующие приложения, размещаемые в Integrated Desktop, облегчая работу сотрудникам информационных отделов. И нельзя ли все программные решения перенести в островки сервисов, связанных между собой набором модулей рабочих процессов?
Данная архитектура развивается, и в ней будут непрерывно отражаться новые возможности платформы. Долгожительство послужит одной из лучших оценок этой архитектуры корпоративного уровня. Открываемый Windows Vista вал новых возможностей, несомненно, повлияет на наши подходы к принятию решений, и у Integrated Desktop есть все шансы оказаться на гребне волны.