Про компанію Послуги Портфоліо Підтримка Відгуки клієнтів Контакнта інформація ТОВ Брутка: розробка програмного забеспечення та створення сайтів

Архів новин


Возможность расширения приложений .NET

Microsoft .NET Framework сильно облегчает встраивание в собственные приложения компонентов, созданных другими разработчиками. Однако это просто, только если известно, к каким компонентам выполняется привязка. Если в момент сборки такие компоненты не известны, что типично для надстроек, то все становится намного сложнее. При расширении своих приложений у разработчиков часто возникают вопросы. Например, надстройки следует хранить в базе данных или на диске? Следует ли в надстройке использовать известный интерфейс или запрашивать тип для активации? Каков наилучший способ использования AppDomain, AppDomainManager и AppDomainSetup?
Эти и другие вопросы решаются в двух выпусках внутреннего бюллетеня CLR за счет введения в библиотеку базовых классов нового пространства имен System.AddIn, которое будет доступно в следующем выпуске Visual Studio® (с кодовым именем "Orcas"). До выхода полного выпуска Visual Studio "Orcas" можно загрузить CTP-версию этих библиотек. Дополнительные сведения можно также найти в статье Блог группы по надстройкам в среде CLR .
В этой серии колонок представлен обзор жизненного цикла разработки расширений приложения на основе надстроек и процесса управления версиями приложения. В данной первой колонке рассматриваются проблемы, с которыми сталкиваются разработчики при первоначальном расширении своих приложений, и описывается, как предлагаемые интерфейсы API облегчают их решение. В следующем месяце основное внимание будет сосредоточено на долгосрочных задачах сохранения работоспособности надстроек даже при изменении узлового приложения: в этой колонке рассматривается пример сборки приложения, его существенно измененная следующая версия и отслеживаются действия, необходимые для сохранения работоспособности исходной надстройки.
Начнем обсуждение задач, связанных с расширением, и преимуществ интерфейсов API. В результате добавления пространства имен System.AddIn и руководства по построению модели управляемых надстроек среда CLR предоставляет решение проблем, являющихся общими для первой версии приложения, и руководство по обеспечению дальнейшей совместимости приложений. См. боковую панель "Терминология расширения" с пояснениями используемых терминов.
Терминология расширения
Узловое приложение Приложение, поддерживающее возможность расширения. Узловое приложение может быть клиентом или сервером (например, Excel, Word, Paint.NET, SQL Server и Exchange Server).
Возможность расширения Механизм управления объектами узлового приложения или расширения функциональности хоста, что иногда называют автоматизацией. Обычно доступен посредством объектной модели, опубликованной как часть пакета SDK.
Пакет SDK Набор общих интерфейсов (API) и ассоциированной документации. Позволяет узловому приложению предоставлять услуги надстройке и наоборот. В различных ситуациях такой пакет SDK может быть предоставлен разными сторонами. Например, пакет SDK может предоставляться узловым приложением для использования ориентированных на конкретные узловые приложения надстроек, надстройкой для использования различными узловыми приложениями (например, проигрыватель Windows Media®) и третьей стороной для использования различными узловыми приложениями и обеспечения взаимодействия между надстройками.
Надстройка (также называется расширением, подключаемым модулем или оснасткой) Сборка, загружаемая узловым приложением. А также средство автоматизации узлового приложения (такого как клиент). Средство, предоставляющее узловому приложению (службе) дополнительные функциональные возможности. Надстройка представляет собой пользовательский код, обычно созданный третьей стороной, который динамически загружается и активируется узловым приложением на основе некоторого контекста (например, запуска узлового приложения или загрузка документа) Надстройка расширяет возможности узлового приложения посредством общего интерфейса API (например, объектной модели или библиотеки управляемых классов), которые доступны надстройке через пакет SDK.
Конвейер Механизмы, позволяющие узловому приложению и надстройке взаимодействовать через независящий от версий безопасный протокол.
Close [x]
Построение расширяемого узлового приложения
После определения узловым приложением требуемой объектной модели взаимодействие узлового приложения со своими надстройками можно разделить на три этапа: обнаружение, активация и управление жизненным циклом. Обнаружение включает нахождение доступных надстроек и предоставление узловому приложению или пользователю достаточной информации, чтобы выбрать надстройку для использования. Активация включает загрузку и запуск выбранной надстройки в подходящей изолированной безопасной "песочнице". Под управлением жизненным циклом подразумевается обеспечение работоспособности надстройки и изменяемых вместе с узловым приложением объектов на протяжении всего времени, пока приложение на них ссылается. При этом узловому приложению предоставляется возможность немедленного отключения надстройки при необходимости. Если не указано иначе, представленный здесь код является частью файла Program.cs из SampleExtensibleCalculator.csproj, который можно загрузить из веб-узла MSDN®Magazine.
Прежде чем переходить к подробному описанию использования надстройки во время выполнения, следует обсудить пакет SDK и определение объектной модели, предоставляемой узловым приложением своим надстройкам. Обсуждаемая модель надстроек поддерживает большое количество сценариев, которые обычно попадают в одну из трех категорий.
В первой категории надстройка предоставляет услугу узловому приложению. Например, почтовый сервер может содержать надстройки для сканирования вирусов, фильтрации нежелательной почты или защиты IP; текстовому процессору может требоваться надстройка для проверки правописания, а веб-обозреватель может содержать надстройки для обработки определенных типов файлов. Этот сценарий иллюстрируется на примере калькулятора. Если посмотреть на код надстройки в SampleCalculatorAddIn.cs, то можно видеть, что данная надстройка предоставляет узловому приложению реализацию функций сложения, вычитания, умножения и деления.
Во второй категории узловое приложение предоставляет услуги надстройке и позволяет ей определять характер автоматизации узлового приложения. В этом сценарии узловое приложение предоставляет услугу надстройке. Большинство надстроек Microsoft® Office попадают в эту категорию: при инициализации надстройки приложение Office передает ей свой корневой объект, позволяя автоматизировать узловое приложение.
С помощью этой модели узловое приложение позволяет третьим сторонам расширять свои функциональные возможности самым неожиданным образом. Уже были рассмотрены надстройки Microsoft Excel®, автоматически замещающие текстовые символы биржевыми сводками в реальном режиме времени, и надстройки Microsoft Word, добавляющие виртуальные ссылки на телефонные номера в документах, которые запускают VoIP-программы и набирают телефонный номер. Бывают приложения, целиком построенные как одна большая надстройка некоторого существующего приложения. Существует несколько приложений для управления отношениями с клиентами, чей клиентский внешний интерфейс целиком содержится в Microsoft Outlook®.
Последняя категория представляет надстройки, которые используются узловым приложением в основном для отображения сведений о действительном состоянии, а не предоставления узловому приложению какой-либо функциональной возможности. Панели инструментов поиска служат таким примером: некоторые такие панели могут добавлять себя к обозревателю, панели задач Windows и клиенту электронной почты, предоставляя одинаковые функциональные возможности вне зависимости от узлового приложения.
В предлагаемом примере узловое приложение предоставляет надстройкам пакет SDK, чтобы использовать их в качестве службы. В этом случае узловое приложение будет использовать надстройку, чтобы реализовать простые функции калькулятора. В представленной модели фактически существует три очень похожих определения объектной модели. Эти компоненты определяются в так называемом "конвейере": представление узлового приложения, представление надстройки и контракты, пересекающие границу изоляции. В дальнейшем конвейер будет обсуждаться более подробно, однако сейчас обратим внимание на представление узлового приложения.
Представленный ниже код является частью представления узлового приложения, а не кодом его ядра, поэтому его можно найти в CalculatorView.cs из hostCalculatorView.csproj:
public abstract class Calculator
{
public abstract double Add(double a, double b);
public abstract double Subtract(double a, double b);
public abstract double Multiply(double a, double b);
public abstract double Divide(double a, double b);
}
Как видно, представление узлового приложения является абстрактным базовым классом, определяющим ожидаемую функциональность надстроек. По отношению к этому представлению узловое приложение программируется напрямую без учета существования границы изоляции между ним и надстройками или того, что надстройка может обладать совершенно другим представлением узлового приложения.

Обнаружение
Первый этап использования надстроек в приложении заключается в их обнаружении: приложению требуется способ нахождения доступных надстроек и получения сведений, достаточных для выбора загружаемой и активируемой надстройки. В зависимости от узлового приложения этот этап обычно выполняется при запуске приложения, загрузке документа или запросе пользователя.
Некоторые высокоуровневые требования к возможности обнаружения включают в себя следующее: способность к нахождению конкретных типов надстроек в указанном месте; предоставление сведений, достаточных узловому приложению или пользователю для выбора используемых надстроек без необходимости их активации; интеллектуальное кэширование, чтобы не требовалось пересчитывать список доступных надстроек; предоставление надстройкам возможности обновления кэша во время установки. Для достижения этих целей можно выполнить следующие действия. Во-первых, определяется место поиска надстроек. В этом примере, ожидается, что надстройки и компоненты должны быть установлены в текущем каталоге, но нередко приложения выбирают несколько различных папок (например, пользовательский каталог данных приложения).
String addInRoot = Environment.CurrentDirectory;
Затем обновляется хранилище надстроек, чтобы внести сведения о недавно установленных надстройках и компонентах конвейера. Класс AddInStore используется для определения, что к чему может подключаться. Эта информация образует то, что называется конвейером.
В данном хранилище содержатся все компоненты, образующие конвейер между узловым приложением и его надстройкой. AddInStore можно обновить при выполнении с помощью интерфейсов API AddInStore.Update и во время установки надстройки с помощью специального средства командной строки, чтобы повысить эффективность запуска процесса обнаружения. Следующий код отвечает за проверку установки новых надстроек. Если новые надстройки или компоненты конвейера не были установлены с момента последнего вызова кода, то проверка выполняется очень быстро.
AddInStore.Update(addInRoot);
Если кэш был обновлен, то узловое приложение будет искать все доступные надстройки, которые могут быть подключены к представлению (абстрактный базовый класс), формируемому узловым приложением. При обработке этого кода выполняется поиск надстройки "Калькулятор" в корневой каталоге, а результат поиска сохраняется.
Collection<AddInToken> tokens =
AddInнр6Store.FindAddIns(typeof(Calculator), addInRoot);
Метод AddInStore.FindAddIns принимает тип искомых надстроек и путь к папке их хранения, и возвращает коллекцию маркеров AddInTokens. Важно отметить, что в данный момент сборки надстройки не загружаются и код надстройки не выполняется. Каждый маркер описывает уникальную надстройку и четыре свойства (имя, номер версии, издатель и описание), предоставляемые надстройкой, чтобы дать приложению/пользователю возможность выбора загружаемых надстроек. В рассматриваемом сценарии калькулятора создается метод ChooseCalculator для отображения маркеров пользователю, что дает ему возможность выбора используемых маркеров.
AddInToken calcToken = ChooseCalculator(tokens);

Активация, изоляция, безопасность и использование "песочниц"
После выбора приложением используемых надстроек оно должно их активировать. Узловому приложению требуется экземпляр, реализующий запрашиваемый абстрактный базовый класс (т.е. представление). Однако в действительность узловому приложению обычно требуется не только это. Также необходимо изолировать надстройку от узлового приложения и других надстроек и реализовать возможность размещения такой надстройки в "песочнице" с конкретным набором разрешений.
Изолированная сборка надстройки может не иметь прямого доступа к коду или ресурсам другой сборки. Платформа .NET Framework использует AppDomains в качестве встроенного в процесс модуля изоляции. Те, кто не знаком с AppDomains, могут их представлять как облегченные процессы. Обычно узловое приложение выполняет свой код в одном AppDomain (обычно это AppDomain по умолчанию, создаваемый при запуске процесса выполнения) и требует, чтобы каждая надстройка обладала собственным AppDomain. За счет изоляции надстроек от узлового приложения и друг от друга достигаются несколько важных преимуществ.
Каждая надстройка находится в собственной папке с собственной базой приложений и загружает собственную сборку без конфликта с узловым приложением или другими надстройками. Этот также позволяет надстройкам обладать собственными файлами конфигурации, которые можно использовать для настройки характерных для каждой настройки функциональных возможностей.
Узловое приложение может регистрировать сбои одной надстройки и отключать ее (и перезапускать при необходимости) без вовлечения в этот процесс узлового приложения или других надстроек.
Надстройку и компоненты, от которых она зависит, можно выгрузить (дополнительные сведения см. в разделе "Управление жизненным циклом" данной колонки).
Надстройки можно помещать в "песочницу" с конкретным набором разрешений (более подробно об этом см. далее).
Однако важно отметить, что при разработке узлового приложения и самой надстройки при программировании напрямую используются абстрактные базовые классы, формирующие представления узлового приложения и надстройки. Поэтому нет необходимости обеспокоиться об ограничениях, связанных с границей изоляции. В этой версии поддерживается изоляция на уровне AppDomain, а будущих версиях можно добавить изоляцию на уровне процессов. Дополнительные сведения об использовании AppDomains в качестве границ безопасности для размещения ненадежных надстроек см. ниже. Дополнительны сведения о надстройках и AppDomains см в статье AppDomain's and Addin's.
Узловому приложению необходимо рассматривать контекст безопасности, с которым загружается и активируется надстройка. При выполнении узлового приложения контексте полного доверия может возникнуть необходимость запуска надстроек с меньшим набором разрешений. Существовавшие ранее интерфейсы API для формирования безопасности и AppDomain являются очень мощными и позволяют настраивать много различных параметров, например, размещение AppDomain в "песочнице". В большинстве случае узловое приложение назначает надстройке параметры безопасности FullTrust, интрасеть или Интернет и полагается на используемую структуру при определении значения каждого из них. Осуждаемые интерфейсы API значительно облегчают выбор одного из этих трех параметров, а также при необходимости предоставляют возможность тонкой настройки параметров установки. Использование всех их в одной строке кода позволяет активировать выбранный маркер AddInToken в новом AppDomain и поместить сборку в "песочницу" в зоне Интернета:
Calculator calculator =
calcToken.Activate<Calculator>(AddInSecurityLevel.Internet);
При выполнении этой единственной строки кода узловому приложению возвращается активированный экземпляр выбранной надстройки. Что стоит за выполнение этого действия?
Структура AddIn создает AppDomain и загружает в него соответствующие сборки. Далее данный код выполняется в данном AppDomain с разрешениями системы безопасности, соответствующими указанному уровню безопасности (в этом случае соответствующими набору разрешений для Интернета). Затем задается ApplicationBase в качестве места размещения действительной сборки, чтобы позволить ей находить свои зависимые компоненты и ресурсы. Затем задается файл конфигурации для данного AppDomain, который должен быть расположен рядом с DLL-файлом сборки. Наконец подключаются требуемые компоненты конвейера, связывающие узловое приложение с данной надстройкой.
Существует другой способ указания собственного набора разрешений для надстроек, позволяющий предоставлять собственный AppDomain. Этот способ позволяет выполнять тонкую настройку AppDomain и параметров системы безопасности для надстройки или даже группы надстроек с одинаковым жизненным циклом и контекстом безопасности и/или использовать преимущества производительности за счет повторного применения AppDomain.
Управление жизненным циклом
Важная часть любой модели надстройки — метод, используемый для управления жизненным циклом объектов надстройки. Управление жизненным COM было целиком основано на подсчете ссылок, тогда как управление жизненным циклом CLR основано на сборщике мусора, а в удаленном управлении CLR используется подход на основе спонсоров/таймаутов. В рассматриваемой системе необходимо пересекать границы AppDomains или процессов и в этих сценариях сборщик мусора CLR уже не способен обеспечить адекватную поддержку. Поэтому системе необходимо предоставить управление жизненным циклом, которое полностью прозрачно для разработчиков узлового приложения и надстроек и максимально облегчает работу разработчиков конвейера (объектной модели). Предоставляемое решение по управлению жизненным циклом более подробно будет обсуждаться в колонке следующего месяца.
Узловое приложение может являться долгосрочной службой, иметь ограничения на память или должно быть способно выгружать надстройки во время выполнения по той или иной причине. Выполнение позволяет выгружать сборки только во время выгрузки AppDomain, в которой они были загружены. Оно не имеет традиционного DllUnload. Это еще один способ полезного использования границы AppDomain: он позволяет восстанавливать ресурсы системы без циклического выполнения процесса.
Если узловому приложению требуется отключить надстройку немедленно, не нужно беспокоится об отслеживании того, какие надстройки принадлежат какому AppDomain. Вместо этого предоставляется класс

2007-03-20

 

Архів новин: новини IT, опис технологій, ціни