Поделиться через


WPF Add-Ins Обзор

Платформа .NET Framework включает модель надстройки, которую разработчики могут использовать для создания приложений, поддерживающих расширяемость надстроек. Эта модель надстройки позволяет создавать надстройки, которые интегрируются с функциональностью приложений и расширяют ее возможности. В некоторых сценариях приложения также должны отображать пользовательские интерфейсы, предоставляемые надстройками. В этом разделе показано, как WPF расширяет модель надстройки .NET Framework, чтобы включить эти сценарии, архитектуру, преимущества и ограничения.

Предпосылки

Требуется знакомство с моделью надстроек .NET Framework. Дополнительные сведения см. в разделе "Надстройки" и "Расширяемость".

Обзор Add-Ins

Чтобы избежать сложностей перекомпиляции и повторного развертывания приложений для включения новых функциональных возможностей, приложения реализуют механизмы расширяемости, позволяющие разработчикам (как сторонним, так и сторонним) создавать другие приложения, которые интегрируются с ними. Наиболее распространенным способом поддержки этого типа расширяемости является использование надстроек (также известных как "надстройки" и "подключаемые модули"). Примеры реальных приложений, которые предоставляют расширяемость с помощью надстроек, включают:

  • Надстройки Internet Explorer.

  • Плагины для Windows Media Player.

  • Надстройки Visual Studio.

Например, модель надстройки проигрывателя Windows Media позволяет сторонним разработчикам реализовать подключаемые модули, которые расширяют проигрыватель Windows Media различными способами, включая создание декодаторов и кодировщиков для форматов мультимедиа, которые не поддерживаются в собственном кодировщике проигрывателем Windows Media (например, DVD, MP3), звуковыми эффектами и скинами. Каждая модель надстроек создается для предоставления функциональных возможностей, уникальных для приложения, хотя существует несколько сущностей и поведения, которые являются общими для всех моделей надстроек.

Три основных сущности типичных решений расширяемости надстроек — контракты, надстройки и хост-приложения. Контракты определяют, как надстройки интегрируются с хост-приложениями двумя способами:

  • Надстройки интегрируются с функциями, реализованными в приложениях-хостах.

  • Хост-приложения предоставляют функциональные возможности для интеграции надстроек.

Чтобы использовать надстройки, хост-приложениям необходимо найти их и загрузить во время выполнения. Следовательно, приложения, поддерживающие надстройки, несут следующие дополнительные обязанности:

  • Обнаружение: поиск надстроек, которые соответствуют контрактам, поддерживаемым хост-приложениями.

  • Активация: загрузка, выполнение и установка связи с надстройками.

  • Изоляция: использование доменов приложений или процессов для установления границ изоляции, которые защищают приложения от потенциальных проблем с безопасностью и выполнением надстроек.

  • Обмен данными. Разрешить надстройкам и хост-приложениям взаимодействовать друг с другом через границы изоляции путем вызова методов и передачи данных.

  • Управление временем существования: загрузка и выгрузка доменов приложений и процессов в чистом, прогнозируемом режиме (см. раздел "Домены приложений").

  • Управление версиями. Обеспечение того, чтобы хост-приложения и надстройки по-прежнему могли взаимодействовать при создании новых версий.

В конечном счете, разработка надежной модели надстроек является нетривиальной задачей. По этой причине платформа .NET Framework предоставляет инфраструктуру для создания моделей надстроек.

Замечание

Дополнительные сведения о надстройках см. в разделе "Надстройки" и "Расширяемость".

Обзор модели .NET Framework Add-In

Модель надстройки .NET Framework, найденная в System.AddIn пространстве имен, содержит набор типов, предназначенных для упрощения разработки расширяемости надстроек. Основная единица модели надстроек .NET Framework — это контракт, определяющий способ взаимодействия ведущего приложения и надстройки друг с другом. Контракт предоставляется хост-приложению с помощью представления контракта, специфического для хост-приложения. Аналогичным образом, специальный вид контракта доступен для надстройки. Адаптер используется, чтобы обеспечить возможность взаимодействия хост-приложения и надстройки между их соответствующими представлениями контракта. Контракты, представления и адаптеры называются сегментами, а набор связанных сегментов представляет собой конвейер. Конвейеры представляют собой основу, на которой модель надстроек .NET Framework поддерживает обнаружение, активацию, изоляцию безопасности, изоляцию выполнения (с помощью доменов приложений и процессов), взаимодействия, управления жизненным циклом и управления версиями.

Сумма этой поддержки позволяет разработчикам создавать надстройки, которые интегрируются с функциональностью ведущего приложения. Однако для некоторых сценариев требуется, чтобы хост-приложения отображали пользовательские интерфейсы, предоставляемые надстройками. Так как каждая технология презентации в .NET Framework имеет собственную модель для реализации пользовательских интерфейсов, модель надстроек .NET Framework не поддерживает какую-либо определенную технологию презентации. Вместо этого WPF расширяет модель надстроек .NET Framework, предоставляя поддержку пользовательского интерфейса для надстроек.

Add-Ins WPF

WPF в сочетании с моделью дополнений .NET Framework позволяет решать различные сценарии, требующие отображения пользовательских интерфейсов с использованием дополнений. В частности, эти сценарии рассматриваются WPF с использованием следующих двух моделей программирования.

  1. Надстройка возвращает пользовательский интерфейс. Надстройка возвращает пользовательский интерфейс в хост-приложение с помощью вызова метода, как определено контрактом. Этот сценарий используется в следующих случаях:

    • Внешний вид пользовательского интерфейса, возвращаемого надстройкой, зависит от данных или условий, которые существуют только во время выполнения, например динамически созданных отчетов.

    • Пользовательский интерфейс для служб, предоставляемых надстройкой, отличается от пользовательского интерфейса ведущих приложений, которые могут использовать надстройку.

    • Надстройка преимущественно выполняет службу для основного приложения и передает информацию о состоянии в основное приложение через пользовательский интерфейс.

  2. Надстройка — это программное расширение. Надстройка — это пользовательский интерфейс, определенный контрактом. Этот сценарий используется в следующих случаях:

    • Надстройка не предоставляет службы, кроме отображаемых, например объявление.

    • Пользовательский интерфейс для служб, предоставляемых надстройкой, является общим для всех ведущих приложений, которые могут использовать такую надстройку, например калькулятор или средство выбора цветов.

Эти сценарии требуют, чтобы объекты пользовательского интерфейса могли передаваться между основным приложением и доменами приложений надстройки. Так как модель надстроек .NET Framework использует удаленное взаимодействие для обмена данными между доменами приложений, объекты, передаваемые между ними, должны быть ремотируемыми.

Ремотируемый объект — это экземпляр класса, который выполняет одно или несколько следующих действий:

Замечание

Дополнительные сведения о создании ремотируемых объектов .NET Framework см. в разделе "Создание объектов Remotable".

Типы пользовательского интерфейса WPF не являются ремотируемыми. Чтобы устранить проблему, WPF расширяет модель надстройки .NET Framework, чтобы включить пользовательский интерфейс WPF, созданный надстройками для отображения из ведущих приложений. Эта поддержка обеспечивается WPF двумя типами: INativeHandleContract интерфейсом и двумя статическими методами, реализованными FrameworkElementAdapters классом: ContractToViewAdapter и ViewToContractAdapter. На высоком уровне эти типы и методы используются следующим образом:

  1. WPF требует, чтобы пользовательские интерфейсы, предоставляемые надстройками, были классами, которые являются производными напрямую или косвенно от FrameworkElement, таких как формы, элементы управления, пользовательские элементы управления, панели макета и страницы.

  2. Когда контракт объявляет, что пользовательский интерфейс будет передаваться между надстройкой и ведущим приложением, он должен быть объявлен как INativeHandleContract (не FrameworkElement); INativeHandleContract представляет собой удалённое представление пользовательского интерфейса надстройки, которое можно передавать через границы изоляции.

  3. Перед передачей из домена приложения надстройки FrameworkElement упаковываются в INativeHandleContract с помощью вызова ViewToContractAdapter.

  4. После передачи в домен приложения узла, INativeHandleContract необходимо перепаковать в FrameworkElement, вызвав ContractToViewAdapter.

Как INativeHandleContract, ContractToViewAdapterи ViewToContractAdapter используются, зависят от конкретного сценария. В следующих разделах приведены сведения о каждой модели программирования.

Add-In возвращает пользовательский интерфейс

Чтобы надстройка возвращала пользовательский интерфейс в хост-приложение, необходимо следующее:

  1. Ведущее приложение, надстройка и конвейер должны быть созданы, как описано в документации по надстройкам .NET Framework и расширяемости .

  2. Контракт должен реализовать IContract и, чтобы вернуть пользовательский интерфейс, контракт должен объявить метод с возвращаемым значением типа INativeHandleContract.

  3. Пользовательский интерфейс, передаваемый между надстройкой и ведущим приложением, должен быть напрямую или косвенно производным от FrameworkElement.

  4. Пользовательский интерфейс, возвращаемый надстройкой, должен быть преобразован из FrameworkElement в INativeHandleContract перед пересечением границы изоляции.

  5. Возвращаемый пользовательский интерфейс должен быть преобразован из INativeHandleContract в FrameworkElement после пересечения границы изоляции.

  6. Ведущее приложение отображает возвращаемый FrameworkElementобъект.

Пример, демонстрирующий реализацию надстройки, возвращающей пользовательский интерфейс, см. в статье "Создание Add-In" для возврата пользовательского интерфейса.

Add-In — это пользовательский интерфейс

Если надстройка является пользовательским интерфейсом, необходимо выполнить следующие действия.

  1. Ведущее приложение, надстройка и конвейер должны быть созданы, как описано в документации по надстройкам .NET Framework и расширяемости .

  2. Контрактный интерфейс для надстройки должен реализовать INativeHandleContract.

  3. Надстройка, передаваемая в хост-приложение, должна быть прямо или косвенно производной от FrameworkElement.

  4. Надстройка должна быть преобразована из FrameworkElement в INativeHandleContract перед пересечением границы изоляции.

  5. Надстройка должна быть преобразована из a в после INativeHandleContractFrameworkElement пересечения границы изоляции.

  6. Ведущее приложение отображает возвращаемый FrameworkElementобъект.

Пример, демонстрирующий, как реализовать дополнение, являющееся пользовательским интерфейсом, см. в статье «Как создать Add-In, который является пользовательским интерфейсом».

Возврат нескольких пользовательских интерфейсов из Add-In

Надстройки часто предоставляют различные пользовательские интерфейсы, которые отображаются основными приложениями. Например, рассмотрим надстройку, которая является пользовательским интерфейсом и также предоставляет сведения о состоянии хост-приложения. Такую надстройку можно реализовать с помощью сочетания методов обоих моделей: Add-In Возвращает пользовательский интерфейс и Add-In Является пользовательским интерфейсом.

Add-Ins и приложения браузера XAML

В примерах до сих пор ведущее приложение было установленным автономным приложением. Но приложения браузера XAML (XBAPs) также могут размещать надстройки, хотя и со следующими дополнительными требованиями к сборке и реализации:

  • Манифест приложения XBAP должен быть настроен специально для скачивания конвейера (папок и сборок) и сборки надстроек в кэш приложения ClickOnce на клиентском компьютере в той же папке, что и XBAP.

  • Код XBAP для обнаружения и загрузки надстроек должен использовать кэш приложений ClickOnce для XBAP, который служит в качестве конвейера и местоположения надстройки.

  • XBAP должен загрузить надстройку в специальный контекст безопасности, если надстройка ссылается на свободные файлы, расположенные на сайте источника; При размещении XBAPs надстройки могут ссылаться только на свободные файлы, расположенные на сайте источника ведущего приложения.

Эти задачи подробно описаны в следующих подразделах.

Настройка конвейера и Add-In для развертывания ClickOnce

XBAPs скачиваются и запускаются из безопасной папки в кэше развертывания ClickOnce. Чтобы XBAP размещал надстройку, также необходимо загрузить конвейер и сборку надстройки в безопасную папку. Для этого необходимо настроить манифест приложения, чтобы включить сборку конвейера и надстройки для скачивания. Это проще всего сделать в Visual Studio, хотя сборка конвейера и надстройки должна находиться в корневой папке проекта XBAP узла, чтобы Visual Studio обнаружила сборки конвейера.

Следовательно, первым шагом является создание конвейера и сборки добавочных компонентов в корневом каталоге проекта XBAP путем установки выходных данных сборки для каждого проекта сборки конвейера и добавочных компонентов. В следующей таблице показаны пути вывода сборки для проектов сборки конвейера и проекта сборки надстроек, которые находятся в том же решении и корневой папке, что и проект XBAP узла.

Таблица 1. Создание выходных путей для сборок конвейера, размещенных XBAP

Проект сборки конвейера Путь вывода сборки
Контракт ..\HostXBAP\Contracts\
Представление Add-In ..\HostXBAP\AddInViews\
Добавить адаптерIn-Side ..\HostXBAP\AddInSideAdapters\
Адаптер Host-Side ..\HostXBAP\HostSideAdapters\
Add-In ..\HostXBAP\AddIns\WPFAddIn1

Следующим шагом является указание сборок конвейера и сборки надстроек в качестве файлов содержимого XBAPs в Visual Studio, выполнив следующие действия.

  1. Включение конвейера и сборки надстроек в проект, щелкнув правой кнопкой мыши каждую папку конвейера в обозревателе решений и выбрав "Включить в проект".

  2. Установите действие сборки для каждой сборки конвейера и сокетной сборки на Содержимое через окно Свойства.

Последним шагом является настройка манифеста приложения для включения файлов сборки конвейера и файла сборки надстройки для скачивания. Файлы должны находиться в папках в корне папки в кэше ClickOnce, который занимает приложение XBAP. Конфигурацию можно достичь в Visual Studio, выполнив следующие действия.

  1. Щелкните правой кнопкой мыши проект XBAP, щелкните "Свойства", нажмите кнопку "Опубликовать" и нажмите кнопку "Файлы приложений ".

  2. В диалоговом окне "Файлы приложений" установите для каждого конвейера и DLL надстройки Состояние публикации на Включить (Авто), а Группу загрузки на (Обязательно).

Использование конвейера и Add-In из базы приложений

Когда конвейер и надстройка настроены для развертывания ClickOnce, они загружаются в ту же папку кэша ClickOnce, что и XBAP. Чтобы использовать конвейер и надстройку из XBAP, код XBAP должен получить их из базы приложений. Различные типы и члены модели надстроек .NET Framework для использования конвейеров и надстроек обеспечивают специальную поддержку этого сценария. Во-первых, путь определяется значением ApplicationBase перечисления. Вы используете это значение с перегрузками соответствующих компонентов надстроек для использования конвейеров, включающих:

Доступ к исходному сайту хоста

Чтобы надстройка может ссылаться на файлы с сайта источника, надстройка должна быть загружена с изоляцией безопасности, эквивалентной хост-приложению. Этот уровень безопасности определяется значением AddInSecurityLevel.Host перечисления и передается методу Activate при активации надстройки.

Архитектура Add-In WPF

На самом высоком уровне, как мы уже видели, WPF позволяет надстройкам .NET Framework реализовывать пользовательские интерфейсы, которые непосредственно или косвенно происходят от FrameworkElement, используя INativeHandleContract, ViewToContractAdapter и ContractToViewAdapter. Результатом является возвращение FrameworkElement ведущего приложения, отображаемого из пользовательского интерфейса в основном приложении.

Для простых сценариев надстроек пользовательского интерфейса этого уровня детализации достаточно для разработчика. Для более сложных сценариев, особенно тех, кто пытается использовать дополнительные службы WPF, такие как макет, ресурсы и привязка данных, более подробные сведения о том, как WPF расширяет модель надстройки .NET Framework с поддержкой пользовательского интерфейса, необходима для понимания его преимуществ и ограничений.

В принципе, WPF не передает пользовательский интерфейс из добавочного модуля в хост-приложение; вместо этого WPF передает дескриптор окна Win32 для пользовательского интерфейса, используя взаимодействие с WPF. Таким образом, когда пользовательский интерфейс из надстройки передается в хост-приложение, происходит следующее:

  • WPF на стороне дополнительного модуля получает дескриптор окна для пользовательского интерфейса, который будет отображаться приложением-хостом. Дескриптор окна инкапсулируется внутренним классом WPF, который является производным от HwndSource и реализует INativeHandleContract. Экземпляр этого класса возвращается ViewToContractAdapter и передается из домена приложения надстройки в домен приложения узла.

  • На стороне ведущего приложения WPF перепаковывает HwndSource внутренний класс WPF, производный от HwndHost и использующий INativeHandleContractего. Экземпляр этого класса возвращается ContractToViewAdapter в хост-приложение.

HwndHost существует для отображения пользовательских интерфейсов, определяемых дескрипторами окон, из пользовательских интерфейсов WPF. Дополнительные сведения см. в разделе WPF и Win32 Interoperation.

В итоге INativeHandleContract, ViewToContractAdapter и ContractToViewAdapter используются, чтобы позволить передавать дескриптор окна для интерфейса WPF из надстройки в хост-приложение, где он инкапсулируется в HwndHost и отображает пользовательский интерфейс хост-приложения.

Замечание

Так как ведущее приложение получает HwndHost, оно не может преобразовать объект, возвращаемый ContractToViewAdapter, в тот тип, в котором он реализован надстройкой (например, UserControl).

По своей природе имеет определенные ограничения, HwndHost которые влияют на их использование ведущими приложениями. Однако WPF расширяет HwndHost, добавляя несколько возможностей для сценариев использования модулей расширения. Эти преимущества и ограничения описаны ниже.

Преимущества WPF Add-In

Поскольку пользовательские интерфейсы надстроек WPF отображаются из приложений-хостов с использованием внутреннего класса, который наследуется от HwndHost, эти интерфейсы ограничены возможностями HwndHost в отношении таких служб пользовательского интерфейса WPF, как макет, отрисовка, привязка данных, стили, шаблоны и ресурсы. Однако WPF расширяет свой внутренний HwndHost подкласс с дополнительными возможностями, которые включают следующие:

  • Переключение между пользовательским интерфейсом основного приложения и интерфейсом надстройки. Обратите внимание, что программная модель надстройки для пользовательского интерфейса требует, чтобы адаптер на стороне надстройки переопределял QueryContract для включения табуляции, независимо от того, является ли надстройка полностью доверенной или частично доверенной.

  • Учет требований доступности для пользовательских интерфейсов надстроек, отображаемых в пользовательских интерфейсах приложения-хоста.

  • Включение безопасного запуска приложений WPF в нескольких сценариях домена приложений.

  • Предотвращение незаконного доступа к дескрипторам окна пользовательского интерфейса надстройки при выполнении надстроек с изоляцией безопасности (т. е. рабочей средой безопасности с ограниченным доверием). Вызов ViewToContractAdapter обеспечивает эту безопасность:

    • Для модели программирования надстройки "надстройка возвращает пользовательский интерфейс", единственным способом передачи дескриптора окна для пользовательского интерфейса надстройки через границу изоляции является вызов ViewToContractAdapter.

    • Для модели программирования «надстройка как модель пользовательского интерфейса» требуется переопределение QueryContract на стороне адаптера надстройки и вызов ViewToContractAdapter (как показано в предыдущих примерах), а также вызов реализации QueryContract адаптера надстройки со стороны адаптера узла.

  • Обеспечение защиты выполнения в нескольких доменах приложений. Из-за ограничений в приложениях необработанные исключения, которые возникают в доменах приложений дополнений, вызывают сбой всего приложения, даже если граница изоляции существует. Тем не менее, WPF и модель надстройки .NET Framework предоставляют простой способ решения этой проблемы и повышения стабильности приложений. Надстройка WPF, отображающая пользовательский интерфейс, создает Dispatcher поток, на котором выполняется домен приложения, если хост-приложение является приложением WPF. Вы можете обнаружить все необработанные исключения, возникающие в домене приложения, обрабатывая событие надстройки WPF UnhandledException. Вы можете получить Dispatcher из свойства CurrentDispatcher.

Ограничения WPF Add-In

Помимо преимуществ, которые WPF добавляет к поведению по умолчанию, предоставляемым HwndSource, HwndHost, и дескрипторам окон, существуют также ограничения для пользовательских интерфейсов надстроек, отображаемых из ведущих приложений.

  • Пользовательские интерфейсы надстроек, отображаемые из хост-приложения, не учитывают поведение обрезки хост-приложения.

  • Концепция воздушного пространства в сценариях взаимодействия также применяется к надстройкам (см. общие сведения о регионах технологий).

  • Службы пользовательского интерфейса ведущего приложения, такие как наследование ресурсов, привязка данных и командная логика, не предоставляются автоматически для пользовательских интерфейсов надстроек. Чтобы предоставить эти услуги надстройке, необходимо обновить конвейерную цепочку.

  • Пользовательский интерфейс надстройки не может быть поворачиваться, масштабироваться, искажаться или подвергаться преобразованиям иным образом (см.Общие сведения о преобразованиях).

  • Содержимое внутри пользовательских интерфейсов надстроек, которых выполняемых с помощью операций рисования из пространства имен System.Drawing, может включать альфа-смешивание. Однако как пользовательский интерфейс надстройки, так и пользовательский интерфейс хост-приложения, содержащий его, должны быть 100% непрозрачными; другими словами, Opacity на обоих свойствах должно быть задано значение 1.

  • AllowsTransparency Если для свойства окна в хост-приложении, содержащем пользовательском интерфейсе надстройки, задано trueзначение, надстройка невидима. Это верно, даже если пользовательский интерфейс надстройки равен 100% непрозрачности (то есть Opacity свойство имеет значение 1).

  • Пользовательский интерфейс надстройки должен отображаться поверх других элементов WPF в том же окне верхнего уровня.

  • Ни один элемент пользовательского интерфейса надстройки не может быть отрисован с помощью VisualBrush. Вместо этого надстройка может создать моментальный снимок созданного пользовательского интерфейса, чтобы создать растровое изображение, которое можно передать в хост-приложение с помощью методов, определенных контрактом.

  • Невозможно воспроизводить мультимедийные файлы из MediaElement в пользовательском интерфейсе надстройки.

  • События мыши, созданные для пользовательского интерфейса надстройки, не принимаются и не инициируются хост-приложением, а IsMouseOver свойство для пользовательского интерфейса хост-приложения имеет значение false.

  • При перемещении фокуса между элементами управления в пользовательском интерфейсе надстройки, события GotFocus и LostFocus не получаются и не вызываются ведущим приложением.

  • Часть основного приложения, содержащая пользовательский интерфейс надстройки, выглядит белым на печати.

  • Все диспетчеры, созданные интерфейсом надстройки, должны быть выключены вручную до выгрузки надстройки владельца, если хост-приложение продолжит выполнение. Контракт может реализовать методы, которые позволяют хост-приложению подать сигнал надстройке перед её выгрузкой, что дает возможность пользовательскому интерфейсу надстройки завершить работу своих диспетчеров.

  • Если пользовательский интерфейс надстройки является InkCanvas или содержит InkCanvas, вы не можете выгрузить надстройку.

Оптимизация производительности

По умолчанию при использовании нескольких доменов приложений различные сборки .NET Framework, необходимые каждому приложению, загружаются в домен этого приложения. В результате время, необходимое для создания доменов приложений и запуска приложений в них, может повлиять на производительность. Однако платформа .NET Framework позволяет сократить время начала, предоставив приложениям общий доступ к сборкам в доменах приложений, если они уже загружены. Это можно сделать с помощью атрибута LoaderOptimizationAttribute , который должен применяться к методу точки входа (Main). В этом случае необходимо использовать только код для реализации определения приложения (см. обзор управления приложениями).

См. также