Compartilhar via


WPF Add-Ins Overview

The .NET Framework includes an add-in model that developers can use to create applications that support add-in extensibility. This add-in model allows the creation of add-ins that integrate with and extend application functionality. In some scenarios, applications also need to display UIs that are provided by add-ins. This topic shows how WPF augments the .NET Framework add-in model to enable these scenarios, the architecture behind it, its benefits, and its limitations.

Este tópico contém as seguintes seções.

  • Prerequisites
  • Add-Ins Overview
  • .NET Framework Add-In Model Overview
  • WPF Add-Ins
  • Add-In Returns a User Interface
  • Add-In Is a User Interface
  • Returning Multiple UIs from an Add-In
  • Add-Ins and XAML Browser Applications
  • WPF Add-In Architecture
  • WPF Add-In Benefits
  • WPF Add-In Limitations
  • Performance Optimization
  • Tópicos relacionados

Prerequisites

Familiarity with the .NET Framework add-in model is required. For more information, see Add-ins e extensibilidade.

Add-Ins Overview

In order to avoid the complexities of application recompilation and redeployment to incorporate new functionality, applications implement extensibility mechanisms that allow developers (both first-party and third-party) to create other applications that integrate with them. The most common way to support this type of extensibility is through the use of add-ins (also known as "add-ons" and "plug-ins"). Examples of real-world applications that expose extensibility with add-ins include:

  • Internet Explorer add-ons.

  • Windows Media Player plug-ins.

  • Visual Studio add-ins.

For example, the Windows Media Player add-in model allows third-party developers to implement "plug-ins" that extend Windows Media Player in a variety of ways, including creating decoders and encoders for media formats that are not supported natively by Windows Media Player (for example, DVD, MP3), audio effects, and skins. Each add-in model is built to expose the functionality that is unique to an application, although there are several entities and behaviors that are common to all add-in models.

The three main entities of typical add-in extensibility solutions are contracts, add-ins, and host applications. Contracts define how add-ins integrate with host applications in two ways:

  • Add-ins integrate with functionality that is implemented by host applications.

  • Host applications expose functionality for add-ins to integrate with.

In order for add-ins to be used, host applications need to find them and load them at run time. Consequently, applications that support add-ins have the following additional responsibilities:

  • Descoberta: Localizando suplementos aderem aos contratos de suporte a aplicativos de host.

  • Ativação: Carregando, execução e estabelecer comunicação com add-ins.

  • Isolamento: Usando domínios de aplicativos ou processos para estabelecer limites de isolamento para protegem aplicativos de potencial problemas de segurança e execução com suplementos.

  • Comunicação: Permitindo que os suplementos e hospedar aplicativos se comuniquem entre si através de limites de isolamento chamando métodos e passagem de dados.

  • Gerenciamento da vida útil: Carregar e descarregar domínios de aplicativos e processos de maneira limpa e previsível (consulte Domínios de Aplicativo).

  • Versionamento: Garantir que os aplicativos de host e suplementos poderá continuar se comunicando quando novas versões de um são criadas.

Ultimately, developing a robust add-in model is a non-trivial undertaking. For this reason, the .NET Framework provides an infrastructure for building add-in models.

Observação

For more detailed information on add-ins, see Add-ins e extensibilidade.

.NET Framework Add-In Model Overview

The .NET Framework add-in model, found in the System.AddIn namespace, contains a set of types that are designed to simplify the development of add-in extensibility. The fundamental unit of the .NET Framework add-in model is the contract, which defines how a host application and an add-in communicate with each other. A contract is exposed to a host application using a host-application-specific view of the contract. Da mesma forma, um add-em-específico do Exibir do contrato é exposto para o suplemento. Um adaptador é usado para permitir que um host, aplicativo e um suplemento para a comunicação entre seus respectivos modos de exibição do contrato. Contracts, views, and adapters are referred to as segments, and a set of related segments constitutes a pipeline. Pipelines are the foundation upon which the .NET Framework add-in model supports discovery, activation, security isolation, execution isolation (using both application domains and processes), communication, lifetime management, and versioning.

The sum of this support allows developers to build add-ins that integrate with the functionality of a host application. However, some scenarios require host applications to display UIs provided by add-ins. Because each presentation technology in the .NET Framework has its own model for implementing UIs, the .NET Framework add-in model does not support any particular presentation technology. Instead, WPF extends the .NET Framework add-in model with UI support for add-ins.

WPF Add-Ins

WPF, in conjunction with the .NET Framework add-in model, allows you to address a wide variety of scenarios that require host applications to display UIs from add-ins. In particular, these scenarios are addressed by WPF with the following two programming models:

  1. The add-in returns a UI. An add-in returns a UI to the host application via a method call, as defined by the contract. This scenario is used in the following cases:

    • A aparência de um UI retornado por um suplemento é dependente de dados ou condições que existem somente em tempo de execução como dinamicamente gerados relatórios.

    • O UI para os serviços fornecidos por um suplemento difere do UI os aplicativos de host que pode usar o add-in.

    • The add-in primarily performs a service for the host application, and reports status to the host application with a UI.

  2. The add-in is a UI. An add-in is a UI, as defined by the contract. This scenario is used in the following cases:

    • An add-in doesn't provide services other than being displayed, such as an advertisement.

    • The UI for services provided by an add-in is common to all host applications that can use that add-in, such as a calculator or color picker.

These scenarios require that UI objects can be passed between host application and add-in application domains. Since the .NET Framework add-in model relies on remoting to communicate between application domains, the objects that are passed between them must be remotable.

A remotable object is an instance of a class that does one or more of the following:

Observação

For more information regarding the creation of remotable .NET Framework objects, see Making Objects Remotable.

O WPF UI tipos são remoto. Para resolver o problema, WPF estende o .NET Framework modelo de suplemento para ativar o WPF UI criado por suplementos para ser exibida em aplicativos de host. Esse suporte é fornecido por WPF por dois tipos: o INativeHandleContract interface e dois métodos estáticos, implementados pelo FrameworkElementAdapters classe: ContractToViewAdapter and ViewToContractAdapter. At a high level, these types and methods are used in the following manner:

  1. WPF requires that UIs provided by add-ins are classes that derive directly or indirectly from FrameworkElement, such as shapes, controls, user controls, layout panels, and pages.

  2. Wherever the contract declares that a UI will be passed between the add-in and the host application, it must be declared as an INativeHandleContract (not a FrameworkElement); INativeHandleContract is a remotable representation of the add-in UI that can be passed across isolation boundaries.

  3. Before being passed from the add-in's application domain, a FrameworkElement is packaged as an INativeHandleContract by calling ViewToContractAdapter.

  4. After being passed to the host application's application domain, the INativeHandleContract must be repackaged as a FrameworkElement by calling ContractToViewAdapter.

How INativeHandleContract, ContractToViewAdapter, and ViewToContractAdapter are used depends on the specific scenario. The following sections provide details for each programming model.

Add-In Returns a User Interface

For an add-in to return a UI to a host application, the following are required:

  1. O aplicativo host add-in e pipeline a devem ser criados, conforme descrito pela .NET Framework Add-ins e extensibilidade documentação.

  2. The contract must implement IContract and, to return a UI, the contract must declare a method with a return value of type INativeHandleContract.

  3. The UI that is passed between the add-in and the host application must directly or indirectly derive from FrameworkElement.

  4. The UI that is returned by the add-in must be converted from a FrameworkElement to an INativeHandleContract before crossing the isolation boundary.

  5. The UI that is returned must be converted from an INativeHandleContract to a FrameworkElement after crossing the isolation boundary.

  6. The host application displays the returned FrameworkElement.

Para obter um exemplo que demonstra como implementar um suplemento que retorna um UI, consulte Como: Criar um suplemento que retorna uma interface do usuário.

Add-In Is a User Interface

When an add-in is a UI, the following are required:

  1. O aplicativo host add-in e pipeline a devem ser criados, conforme descrito pela .NET Framework Add-ins e extensibilidade documentação.

  2. The contract interface for the add-in must implement INativeHandleContract.

  3. The add-in that is passed to the host application must directly or indirectly derive from FrameworkElement.

  4. The add-in must be converted from a FrameworkElement to an INativeHandleContract before crossing the isolation boundary.

  5. The add-in must be converted from an INativeHandleContract to a FrameworkElement after crossing the isolation boundary.

  6. The host application displays the returned FrameworkElement.

Para obter um exemplo que demonstra como implementar um suplemento é um UI, consulte Como: Criar um suplemento que é uma interface do usuário.

Returning Multiple UIs from an Add-In

Add-ins geralmente fornecem várias UIs para aplicativos de host para exibição. For example, consider an add-in that is a UI that also provides status information to the host application, also as a UI. Um add-in como isso pode ser implementado usando uma combinação de técnicas de ambos os suplemento retorna uma Interface do usuário e Add-In É uma Interface de usuário modelos.

Add-Ins and XAML Browser Applications

In the examples so far, the host application has been an installed standalone application. But XAML browser applications (XBAPs) can also host add-ins, albeit with the following additional build and implementation requirements:

  • The XBAP application manifest must be configured specially to download the pipeline (folders and assemblies) and add-in assembly to the ClickOnce application cache on the client machine, in the same folder as the XBAP.

  • The XBAP code to discover and load add-ins must use the ClickOnce application cache for the XBAP as the pipeline and add-in location.

  • The XBAP must load the add-in into a special security context if the add-in references loose files that are located at the site of origin; when hosted by XBAPs, add-ins can only reference loose files that are located at the host application's site of origin.

These tasks are described in detail in the following subsections.

Configuring the Pipeline and Add-In for ClickOnce Deployment

XBAPs are downloaded to and run from a safe folder in the ClickOnce deployment cache. In order for an XBAP to host an add-in, the pipeline and add-in assembly must also be downloaded to the safe folder. To achieve this, you need to configure the application manifest to include both the pipeline and add-in assembly for download. This is most easily done in Visual Studio, although the pipeline and add-in assembly needs to be in the host XBAP project's root folder in order for Visual Studio to detect the pipeline assemblies.

Consequently, the first step is to build the pipeline and add-in assembly to the XBAP project's root by setting the build output of each pipeline assembly and add-in assembly projects. The following table shows the build output paths for pipeline assembly projects and add-in assembly project that are in the same solution and root folder as the host XBAP project.

Tabela 1: Construir caminhos de saída para os módulos de Pipeline que são hospedados por um XBAP

Pipeline assembly project

Build output path

Contract

.. \HostXBAP\Contracts\

Add-In View

.. \HostXBAP\AddInViews\

Add-In-Side Adapter

.. \HostXBAP\AddInSideAdapters\

Host-Side Adapter

.. \HostXBAP\HostSideAdapters\

Add-In

.. \HostXBAP\AddIns\WPFAddIn1

The next step is to specify the pipeline assemblies and add-in assembly as the XBAPs content files in Visual Studio by doing the following:

  1. Including the pipeline and add-in assembly in the project by right-clicking each pipeline folder in Solution Explorer and choosing Include In Project.

  2. Setting the Build Action of each pipeline assembly and add-in assembly to Content from the Properties window.

The final step is to configure the application manifest to include the pipeline assembly files and add-in assembly file for download. The files should be located in folders at the root of the folder in the ClickOnce cache that the XBAP application occupies. The configuration can be achieved in Visual Studio by doing the following:

  1. Com o botão direito do XBAP do projeto, clique em Propriedades, clique em Publicare, em seguida, clique no Arquivos de aplicativo botão.

  2. In the Application Files dialog, set the Publish Status of each pipeline and add-in DLL to Include (Auto), and set the Download Group for each pipeline and add-in DLL to (Required).

Using the Pipeline and Add-In from the Application Base

Quando o suplemento e pipeline são configurados para ClickOnce implantação, que são baixadas para o mesmo ClickOnce pasta de cache, como o XBAP. To use the pipeline and add-in from the XBAP, the XBAP code must get them from the application base. The various types and members of the .NET Framework add-in model for using pipelines and add-ins provide special support for this scenario. Firstly, the path is identified by the ApplicationBase enumeration value. You use this value with overloads of the pertinent add-in members for using pipelines that include the following:

Accessing the Host's Site of Origin

To ensure that an add-in can reference files from the site of origin, the add-in must be loaded with security isolation that is equivalent to the host application. This security level is identified by the AddInSecurityLevel.Host enumeration value, and passed to the Activate method when an add-in is activated.

WPF Add-In Architecture

At the highest level, as we've seen, WPF enables .NET Framework add-ins to implement UIs (that derive directly or indirectly from FrameworkElement) using INativeHandleContract, ViewToContractAdapter and ContractToViewAdapter. O resultado é que o aplicativo host é retornado um FrameworkElement que é exibido de UI no aplicativo host.

For simple UI add-in scenarios, this is as much detail as a developer needs. Para cenários mais complexos, especialmente aqueles que tente utilizar adicionais WPF serviços, como o layout, recursos e os dados de vinculação, conhecimento mais detalhado de como WPF estende o .NET Framework modelo de suplemento com UI suporte é necessária para entender seus benefícios e limitações.

Fundamentally, WPF doesn't pass a UI from an add-in to a host application; instead, WPF passes the Win32 window handle for the UI by using WPF interoperability. As such, when a UI from an add-in is passed to a host application, the following occurs:

  • On the add-in side, WPF acquires a window handle for the UI that will be displayed by the host application. The window handle is encapsulated by an internal WPF class that derives from HwndSource and implements INativeHandleContract. An instance of this class is returned by ViewToContractAdapter and is marshaled from the add-in's application domain to the host application's application domain.

  • On the host application side, WPF repackages the HwndSource as an internal WPF class that derives from HwndHost and consumes INativeHandleContract. An instance of this class is returned by ContractToViewAdapter to the host application.

HwndHost exists to display UIs, identified by window handles, from WPF UIs. For more information, see WPF e a interoperação de Win32.

In summary, INativeHandleContract, ViewToContractAdapter, and ContractToViewAdapter exist to allow the window handle for a WPF UI to be passed from an add-in to a host application, where it is encapsulated by a HwndHost and displayed the host application's UI.

Observação

Because the host application gets an HwndHost, the host application cannot convert the object that is returned by ContractToViewAdapter to the type it is implemented as by the add-in (for example, a UserControl).

By its nature, HwndHost has certain limitations that affect how host applications can use them. However, WPF extends HwndHost with several capabilities for add-in scenarios. These benefits and limitations are described below.

WPF Add-In Benefits

Porque WPF suplemento UIs são exibidos a partir de aplicativos de host usando uma classe interna que deriva de HwndHost, os UIs são restringidos pelos recursos do HwndHost com relação a WPF UI serviços como o layout, processamento, ligação de dados, estilos, modelos e recursos. However, WPF augments its internal HwndHost subclass with additional capabilities that include the following:

  • Tabbing between a host application's UI and an add-in's UI. Observe que o "suplemento é um UI" requer o modelo de programação substituir o adaptador de adicionar no lado QueryContract para habilitar a navegação por TAB, se o suplemento é totalmente confiável ou parcialmente confiável.

  • Honoring accessibility requirements for add-in UIs that are displayed from host application UIs.

  • Enabling WPF applications to run safely in multiple application domain scenarios.

  • Preventing illegal access to add-in UI window handles when add-ins run with security isolation (that is, a partial-trust security sandbox). Calling ViewToContractAdapter ensures this security:

    • For the "add-in returns a UI" programming model, the only way to pass the window handle for an add-in UI across the isolation boundary is to call ViewToContractAdapter.

    • For the "add-in is a UI" programming model, overriding QueryContract on the add-in-side adapter and calling ViewToContractAdapter (as shown in the preceding examples) is required, as is calling the add-in-side adapter's QueryContract implementation from the host-side adapter.

  • Providing multiple application domain execution protection. Due to limitations with application domains, unhandled exceptions that are thrown in add-in application domains cause the entire application to crash, even though the isolation boundary exists. However, WPF and the .NET Framework add-in model provide a simple way to work around this problem and improve application stability. A WPF add-in that displays a UI creates a Dispatcher for the thread that the application domain runs on, if the host application is a WPF application. You can detect all unhandled exceptions that occur in the application domain by handling the UnhandledException event of the WPF add-in's Dispatcher. You can get the Dispatcher from the CurrentDispatcher property.

WPF Add-In Limitations

Beyond the benefits that WPF adds to the default behaviors supplied by HwndSource, HwndHost, and window handles, there are also limitations for add-in UIs that are displayed from host applications:

  • Add-in UIs displayed from a host application do not respect the host application's clipping behavior.

  • The concept of airspace in interoperability scenarios also applies to add-ins (see Visão geral de regiões de tecnologia).

  • A host application's UI services, such as resource inheritance, data binding, and commanding, are not automatically available to add-in UIs. To provide these services to the add-in, you need to update the pipeline.

  • An add-in UI cannot be rotated, scaled, skewed, or otherwise affected by a transformation (see Visão Geral sobre Transformações).

  • Content inside add-in UIs that is rendered by drawing operations from the System.Drawing namespace can include alpha blending. However, both an add-in UI and the host application UI that contains it must be 100% opaque; in other words, the Opacity property on both must be set to 1.

  • If the AllowsTransparency property of a window in the host application that contains an add-in UI is set to true, the add-in is invisible. This is true even if the add-in UI is 100% opaque (that is, the Opacity property has a value of 1).

  • An add-in UI must appear on top of other WPF elements in the same top-level window.

  • No portion of an add-in's UI can be rendered using a VisualBrush. Instead, the add-in may take a snapshot of the generated UI to create a bitmap that can be passed to the host application using methods defined by the contract.

  • Media files cannot be played from a MediaElement in an add-in UI.

  • Mouse events generated for the add-in UI are neither received nor raised by the host application, and the IsMouseOver property for host application UI has a value of false.

  • When focus shifts between controls in an add-in UI, the GotFocus and LostFocus events are neither received nor raised by the host application.

  • The portion of a host application that contains an add-in UI appears white when printed.

  • All dispatchers (see Dispatcher) created by the add-in UI must be shut down manually before the owner add-in is unloaded if the host application continues execution. The contract can implement methods that allow the host application to signal the add-in before the add-in is unloaded, thereby allowing the add-in UI to shut down its dispatchers.

  • Se um add-in UI é um InkCanvas ou contém um InkCanvas, não é possível descarregar o add-in.

Performance Optimization

By default, when multiple application domains are used, the various .NET Framework assemblies required by each application are all loaded into that application's domain. As a result, the time required for creating new application domains and starting applications in them might affect performance. No entanto, o .NET Framework fornece uma maneira de reduzir os tempos de início instruindo aplicativos compartilhem os assemblies em domínios de aplicativo se elas já forem carregadas. You do this by using the LoaderOptimizationAttribute attribute, which must be applied to the entry point method (Main). In this case, you must use only code to implement your application definition (see Visão Geral do Gerenciamento de Aplicativo).

Consulte também

Referência

LoaderOptimizationAttribute

Conceitos

Add-ins e extensibilidade

Domínios de Aplicativo

Outros recursos

.NET Framework Remoting Overview

Making Objects Remotable

Tópicos Como