Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O .NET Framework inclui um modelo de complementos que os desenvolvedores podem usar para criar aplicações que oferecem suporte à extensibilidade de complementos. Esse modelo de suplemento permite a criação de suplementos que se integram e estendem a funcionalidade do aplicativo. Em alguns cenários, os aplicativos também precisam exibir interfaces de usuário fornecidas por suplementos. Este tópico mostra como o WPF aumenta o modelo de suplemento do .NET Framework para habilitar esses cenários, a arquitetura por trás dele, seus benefícios e suas limitações.
Pré-requisitos
É necessária familiaridade com o modelo de suplementos do .NET Framework. Para obter mais informações, consulte Suplementos e extensibilidade.
Visão geral Add-Ins
Para evitar as complexidades da recompilação e reimplantação de aplicativos para incorporar novas funcionalidades, os aplicativos implementam mecanismos de extensibilidade que permitem que os desenvolvedores (primários e de terceiros) criem outros aplicativos que se integrem a eles. A maneira mais comum de suportar esse tipo de extensibilidade é através do uso de suplementos (também conhecidos como "complementos" e "plug-ins"). Exemplos de aplicações do dia a dia que demonstram a extensibilidade com complementos incluem:
Complementos para o Internet Explorer.
Plug-ins do Windows Media Player.
Suplementos do Visual Studio.
Por exemplo, o modelo de suplemento do Windows Media Player permite que desenvolvedores de terceiros implementem "plug-ins" que estendem o Windows Media Player de várias maneiras, incluindo a criação de decodificadores e codificadores para formatos de mídia que não são suportados nativamente pelo Windows Media Player (por exemplo, DVD, MP3), efeitos de áudio e capas. Cada modelo de suplemento é criado para expor a funcionalidade que é exclusiva de um aplicativo, embora existam várias entidades e comportamentos que são comuns a todos os modelos de suplemento.
As três entidades principais das soluções típicas de extensibilidade de suplementos são contratos, suplementos e aplicações anfitriãs. Os contratos definem como os suplementos se integram aos aplicativos host de duas maneiras:
Os suplementos integram-se com a funcionalidade implementada por aplicações anfitriãs.
As aplicações anfitriãs expõem funcionalidades para a integração de complementos.
Para que os suplementos sejam usados, as aplicações anfitriãs devem encontrá-los e carregá-los em tempo de execução. Consequentemente, os aplicativos que suportam suplementos têm as seguintes responsabilidades adicionais:
Descoberta: Encontrar suplementos que aderem a contratos suportados por aplicações anfitriãs.
Ativação: Carregar, executar e estabelecer comunicação com suplementos.
Isolamento: usando domínios ou processos de aplicativos para estabelecer limites de isolamento que protegem os aplicativos de possíveis problemas de segurança e execução com suplementos.
Comunicação: Permite que suplementos e aplicativos host se comuniquem entre si através dos limites de isolamento, chamando métodos e passando dados.
Gerenciamento de tempo de vida: Carregando e descarregando domínios e processos de aplicativos de maneira limpa e previsível (consulte Domínios de aplicativos).
Controle de versão: Garantir que os aplicativos host e suplementos ainda possam se comunicar quando novas versões de ambos forem criadas.
Em última análise, o desenvolvimento de um modelo de suplemento robusto é uma tarefa não trivial. Por esse motivo, o .NET Framework fornece uma infraestrutura para o desenvolvimento de modelos de extensões.
Observação
Para obter informações mais detalhadas sobre suplementos, consulte Suplementos e extensibilidade.
Visão geral do modelo de Add-In do .NET Framework
O modelo de suplemento do .NET Framework, encontrado no System.AddIn namespace, contém um conjunto de tipos projetados para simplificar o desenvolvimento da extensibilidade do suplemento. A unidade fundamental do modelo de suplemento do .NET Framework é o contrato, que define como um aplicativo host e um suplemento se comunicam entre si. Um contrato é exposto a uma aplicação anfitriã usando uma visualização específica da aplicação anfitriã do contrato. Da mesma forma, uma visão específica do contrato, relativa ao suplemento, é disponibilizada ao suplemento. Um adaptador é utilizado para permitir que uma aplicação anfitriã e um complemento comuniquem entre as suas respetivas vistas do contrato. Contratos, visões e adaptadores são chamados de segmentos, e um conjunto de segmentos relacionados constitui um pipeline. Os pipelines são a base sobre a qual o modelo de suplemento do .NET Framework oferece suporte à descoberta, ativação, isolamento de segurança, isolamento de execução (usando domínios e processos de aplicativos), comunicação, gerenciamento de tempo de vida e controle de versão.
A soma desse suporte permite que os desenvolvedores criem suplementos que se integram com a funcionalidade de um aplicativo host. No entanto, alguns cenários exigem que os aplicativos host exibam interfaces de usuário fornecidas por suplementos. Como cada tecnologia de apresentação no .NET Framework tem seu próprio modelo para implementar interfaces de usuário, o modelo de suplemento do .NET Framework não oferece suporte a nenhuma tecnologia de apresentação específica. Em vez disso, o WPF estende o modelo de complemento do .NET Framework com suporte para a interface do utilizador para complementos.
WPF Add-Ins
O WPF, em conjunto com o modelo de complementos do .NET Framework, permite abordar uma ampla variedade de cenários que exigem que as aplicações anfitriãs exibam interfaces de utilizador de complementos. Em particular, esses cenários são abordados pelo WPF com os dois seguintes modelos de programação:
O suplemento devolve um UI. Um complemento devolve uma interface do utilizador à aplicação anfitriã através de uma chamada de método, conforme definido pelo contrato. Esse cenário é usado nos seguintes casos:
A aparência de uma interface do utilizador retornada por um suplemento depende de dados ou condições que estão disponíveis apenas durante o tempo de execução, como relatórios gerados dinamicamente.
A interface do usuário para serviços fornecidos por um suplemento difere da interface do usuário dos aplicativos host que podem usar o suplemento.
O suplemento executa principalmente um serviço para o aplicativo host e relata o status para o aplicativo host com uma interface do usuário.
O suplemento é uma interface de utilizador. Um suplemento é uma interface de utilizador, conforme definido pelo contrato. Esse cenário é usado nos seguintes casos:
Um suplemento não fornece outros serviços além de ser exibido, como um anúncio.
A interface de utilizador para serviços fornecidos por um suplemento é comum a todas as aplicações hospedeiras que podem usar esse suplemento, como uma calculadora ou seletor de cores.
Esses cenários exigem que os objetos da interface do usuário possam ser passados entre domínios de aplicativo host e aplicativo de suplemento. Como o modelo de suplemento do .NET Framework utiliza comunicação remota entre domínios de aplicação, os objetos que são passados entre eles devem ser remotáveis.
Um objeto remotable é uma instância de uma classe que executa um ou mais dos seguintes procedimentos:
Deriva da MarshalByRefObject classe.
Implementa a interface ISerializable.
Tem o SerializableAttribute atributo aplicado.
Observação
Para obter mais informações sobre a criação de objetos .NET Framework remotable, consulte Making Objects Remotable.
Os tipos de interface do utilizador do WPF não são remotáveis. Para resolver o problema, o WPF estende o modelo de complemento do .NET Framework para permitir que a interface do utilizador do WPF criada por complementos seja exibida pelas aplicações host. Este suporte é fornecido pelo WPF por dois tipos: a INativeHandleContract interface e dois métodos estáticos implementados pela FrameworkElementAdapters classe: ContractToViewAdapter e ViewToContractAdapter. Em um alto nível, esses tipos e métodos são usados da seguinte maneira:
WPF requer que as interfaces de utilizador fornecidas por complementos sejam classes que derivam direta ou indiretamente de FrameworkElement, como formas, controlos, controlos de utilizador, painéis de layout e páginas.
Sempre que o contrato declarar que uma IU será passada entre o suplemento e o aplicativo host, ela deve ser declarada como um INativeHandleContract (não um FrameworkElement); INativeHandleContract é uma representação remotável da IU do suplemento que pode ser passada através dos limites de isolamento.
Antes de ser passado do domínio da aplicação da extensão, um FrameworkElement é empacotado como um INativeHandleContract chamando ViewToContractAdapter.
Depois de ser passado para o domínio da aplicação anfitriã, o INativeHandleContract deve ser reempacotado como um FrameworkElement chamando ContractToViewAdapter.
Como INativeHandleContract, ContractToViewAdaptere ViewToContractAdapter são usados depende do cenário específico. As seções a seguir fornecem detalhes para cada modelo de programação.
Add-In retorna uma interface de usuário
Para que um suplemento retorne uma interface de utilizador a uma aplicação anfitriã, são necessárias as seguintes condições:
O aplicativo host, o suplemento e o pipeline devem ser criados, conforme descrito pela documentação de Suplementos e Extensibilidade do .NET Framework.
O contrato deve implementar IContract e, para retornar uma interface do usuário, o contrato deve declarar um método com um valor de retorno do tipo INativeHandleContract.
A interface que é passada entre o complemento e o aplicativo host deve derivar direta ou indiretamente do FrameworkElement.
A interface de utilizador retornada pelo suplemento deve ser convertida de um FrameworkElement para um INativeHandleContract antes de cruzar o limite de isolamento.
A interface do usuário retornada deve ser convertida de um INativeHandleContract para um FrameworkElement depois de cruzar o limite de isolamento.
A aplicação anfitriã exibe o retornado FrameworkElement.
Para obter um exemplo que demonstra como implementar um complemento que retorna uma interface do utilizador, consulte Crie um Add-In que retorna uma interface do utilizador.
Add-In é uma interface de usuário
Quando uma UI é um suplemento, são necessários os seguintes elementos:
O aplicativo host, o suplemento e o pipeline devem ser criados, conforme descrito pela documentação de Suplementos e Extensibilidade do .NET Framework.
A interface de contrato do suplemento deve implementar INativeHandleContract.
O suplemento que é passado para o aplicativo host deve derivar direta ou indiretamente de FrameworkElement.
O suplemento deve ser convertido de um FrameworkElement para um INativeHandleContract antes de cruzar a fronteira de isolamento.
O suplemento deve ser convertido de um INativeHandleContract para um FrameworkElement depois de cruzar o limite de isolamento.
A aplicação anfitriã exibe o retornado FrameworkElement.
Para obter um exemplo que demonstra como implementar um complemento como interface do utilizador, consulte Criar uma Add-In como interface do utilizador.
Devolvendo várias interfaces de utilizador de um Add-In
Os suplementos geralmente fornecem várias interfaces de utilizador para os aplicativos host exibirem. Por exemplo, considere um suplemento que é uma interface do usuário que também fornece informações de status para o aplicativo host, também como uma interface do usuário. Um suplemento como este pode ser implementado usando uma combinação de técnicas dos modelos Add-In Retorna uma Interface do Usuário e Add-In É uma Interface do Usuário .
Aplicativos de navegador Add-Ins e XAML
Nos exemplos até agora, o aplicativo host tem sido um aplicativo autônomo instalado. Mas os aplicativos de navegador XAML (XBAPs) também podem hospedar suplementos, embora com os seguintes requisitos adicionais de compilação e implementação:
O manifesto da aplicação XBAP deve ser configurado especificamente para baixar o pipeline (pastas e assemblies) e o assembly do add-in para o cache da aplicação ClickOnce na máquina cliente, na mesma pasta que o XBAP.
O código XBAP para descobrir e carregar add-ins deve utilizar o cache da aplicação ClickOnce para o XBAP como o pipeline e o local do add-in.
O XBAP deve carregar o suplemento em um contexto de segurança especial se o suplemento fizer referência a arquivos soltos localizados no local de origem; quando hospedados por XBAPs, os suplementos só podem fazer referência a arquivos soltos localizados no site de origem do aplicativo host.
Essas tarefas são descritas em detalhes nas subseções a seguir.
Configurando o pipeline e o Add-In para implantação do ClickOnce
XBAPs são baixados e executados a partir de uma pasta segura no cache de implantação do ClickOnce. Para que um XBAP hospede um suplemento, o pipeline e o conjunto do suplemento também devem ser transferidos para a pasta segura. Para conseguir isso, é necessário configurar o manifesto da aplicação para incluir tanto o pipeline quanto a assemblagem do suplemento para download. Isso é feito mais facilmente no Visual Studio, embora o fluxo de trabalho e o assembly de suplemento precisem estar na pasta raiz do projeto XBAP do host para que o Visual Studio detete os assemblies do fluxo de trabalho.
Consequentemente, a primeira etapa é construir o pipeline e o assembly de complemento para a raiz do projeto XBAP, definindo a saída de compilação de cada assembly de pipeline e projetos de complemento. A tabela a seguir mostra os caminhos de saída de compilação para projetos de assembly de pipeline e projetos de assembly de complemento que estão na mesma solução e na pasta raiz que o projeto XBAP host.
Tabela 1: Criar caminhos de saída para os assemblies de pipeline que são hospedados por um XBAP
| Projeto de construção de tubagem | Construir caminho de saída |
|---|---|
| Contrato | ..\HostXBAP\Contracts\ |
| Add-In Vista | ..\HostXBAP\AddInViews\ |
| Adicionar AdaptadorIn-Side | ..\HostXBAP\AddInSideAdapters\ |
| Adaptador Host-Side | ..\HostXBAP\HostSideAdapters\ |
| Add-In | ..\HostXBAP\AddIns\WPFAddIn1 |
A próxima etapa é especificar os assemblies de pipelines e os assemblies de complemento como arquivos de conteúdo de XBAPs no Visual Studio, procedendo da seguinte forma:
Para incluir o pipeline e o assembly de suplemento no projeto, clique com o botão direito do rato em cada pasta de pipeline no Gerenciador de Soluções e selecione Incluir no Projeto.
Definindo a ação de compilação de cada assembly de pipeline e assembly de suplemento como Conteúdo na janela Propriedades .
A etapa final é configurar o manifesto da aplicação para incluir os arquivos de assembly de pipeline e o arquivo de assembly de add-in para baixar. Os arquivos devem estar localizados em pastas na raiz da pasta no cache ClickOnce que o aplicativo XBAP ocupa. A configuração pode ser obtida no Visual Studio fazendo o seguinte:
Clique com o botão direito do mouse no projeto XBAP, clique em Propriedades, clique em Publicar e, em seguida, clique no botão Arquivos de Aplicativo .
Na caixa de diálogo Arquivos de Aplicação, defina o Status de Publicação de cada pipeline e DLL de complemento como Incluir (Auto) e defina o Grupo de Download para cada pipeline e DLL de complemento como (Obrigatório).
Usando o pipeline e o Add-In da base de aplicativos
Quando o pipeline e o suplemento são configurados para implantação do ClickOnce, eles são baixados para a mesma pasta de cache do ClickOnce que o XBAP. Para usar o pipeline e o complemento do XBAP, o código XBAP deve obtê-los pela base da aplicação. Os vários tipos e membros do modelo de complementos do .NET Framework para utilizar pipelines e complementos oferecem suporte especial para este cenário. Em primeiro lugar, o caminho é identificado pelo valor de enumeração ApplicationBase. Você utiliza este valor com sobrecargas dos membros relevantes dos complementos para usar pipelines que incluem o seguinte:
Acesso ao Site de Origem do Anfitrião
Para garantir que um suplemento possa fazer referência a arquivos do site de origem, o suplemento deve ser carregado com isolamento de segurança equivalente ao aplicativo host. O nível de segurança é identificado pela enumeração de valor AddInSecurityLevel.Host e passado para o método Activate quando um suplemento é ativado.
Arquitetura Add-In WPF
No nível mais alto, como vimos, o WPF permite que os suplementos do .NET Framework implementem interfaces de usuário (que derivam direta ou indiretamente de FrameworkElement) usando INativeHandleContract, ViewToContractAdapter e ContractToViewAdapter. O resultado é que o aplicativo host é retornado um FrameworkElement que é exibido da interface do usuário no aplicativo host.
Para cenários simples de suplementos de interface do usuário, isso é o máximo de detalhes que um desenvolvedor precisa. Para cenários mais complexos, particularmente aqueles que tentam utilizar serviços WPF adicionais, como layout, recursos e vinculação de dados, é necessário um conhecimento mais detalhado de como o WPF estende o modelo de suplemento do .NET Framework com suporte à interface do usuário para entender seus benefícios e limitações.
Fundamentalmente, o WPF não passa uma interface do usuário de um suplemento para um aplicativo host; em vez disso, o WPF passa o identificador de janela do Win32 para a interface do usuário usando a interoperabilidade do WPF. Como tal, quando uma interface do usuário de um suplemento é passada para um aplicativo host, ocorre o seguinte:
No lado do suplemento, o WPF adquire um identificador de janela para a interface do usuário que será exibido pelo aplicativo host. O identificador de janela é encapsulado por uma classe WPF interna que deriva de HwndSource e implementa INativeHandleContract. Uma instância dessa classe é retornada pelo ViewToContractAdapter e é empacotada do domínio do aplicativo do suplemento para o domínio do aplicativo host.
No lado do aplicativo host, o WPF reempacota o HwndSource como uma classe WPF interna que deriva e HwndHost consome INativeHandleContract. Uma instância desta classe é retornada pelo ContractToViewAdapter ao aplicativo host.
HwndHost existe para exibir interfaces de usuário, identificadas por identificadores de janela, a partir de interfaces de usuário WPF. Para obter mais informações, consulte WPF e Win32 Interoperation.
Em resumo, INativeHandleContract, ViewToContractAdapter, e ContractToViewAdapter existem para permitir que o identificador de janela para uma interface do usuário do WPF seja passado de um suplemento para um aplicativo host, onde ele é encapsulado por um HwndHost e exibido a interface do usuário do aplicativo host.
Observação
Como o aplicativo host obtém um HwndHost, o aplicativo host não pode converter o objeto que é retornado por ContractToViewAdapter para o tipo em que é implementado pelo suplemento (por exemplo, um UserControl).
Por sua natureza, HwndHost tem certas limitações que afetam como os aplicativos host podem usá-los. No entanto, o WPF amplia-se HwndHost com várias capacidades para cenários de complemento. Esses benefícios e limitações são descritos abaixo.
Benefícios do WPF Add-In
Como as interfaces de utilizador do suplemento WPF são exibidas através de aplicativos host utilizando uma classe interna que deriva de HwndHost, essas interfaces são restringidas pelas capacidades de HwndHost no que diz respeito aos serviços de interface do utilizador do WPF, tais como layout, renderização, vinculação de dados, estilos, modelos e recursos. No entanto, o WPF aumenta sua subclasse interna HwndHost com recursos adicionais que incluem o seguinte:
Tabulação entre a interface do usuário de um aplicativo host e a interface do usuário de um suplemento. Observe que o modelo de programação "add-in is a UI" requer que o adaptador do lado do suplemento substitua QueryContract para habilitar a tabulação, quer o suplemento seja totalmente confiável ou parcialmente confiável.
Honrando os requisitos de acessibilidade para interfaces de usuário de suplemento que são exibidas a partir de interfaces de usuário de aplicativo host.
Permitindo que os aplicativos WPF sejam executados com segurança em vários cenários de domínio de aplicativo.
Prevenção de acesso ilegal a handles de janelas da interface do utilizador dos suplementos quando estes são executados com isolamento de segurança, ou seja, num ambiente de segurança com confiança parcial. Ligar ViewToContractAdapter garante essa segurança:
Para o modelo de programação "complemento retorna uma interface do usuário", a única maneira de passar o identificador de janela para uma interface do usuário de complemento além da barreira de isolamento é chamar ViewToContractAdapter.
Para o modelo de programação "add-in is a UI", é necessário substituir o adaptador do lado do add-in QueryContract e chamar ViewToContractAdapter (como mostrado nos exemplos anteriores), assim como chamar a implementação
QueryContractdo adaptador do lado do add-in a partir do adaptador do lado do host.
Fornecendo proteção de execução de vários domínios de aplicativos. Devido a limitações dos domínios de aplicativos, exceções não tratadas que são lançadas em domínios de suplemento do aplicativo fazem com que o aplicativo inteiro crashe, mesmo que o limite de isolamento exista. No entanto, o WPF e o modelo de suplemento do .NET Framework fornecem uma maneira simples de contornar esse problema e melhorar a estabilidade do aplicativo. Um suplemento WPF que exibe uma interface de usuário cria um Dispatcher para o thread em que o domínio de aplicação é executado, se a aplicação anfitriã for uma aplicação WPF. Você pode detetar todas as exceções não tratadas que ocorrem no domínio da aplicação ao manipular o evento UnhandledException do suplemento Dispatcher WPF. Você pode obter o Dispatcher da propriedade CurrentDispatcher.
Limitações do WPF Add-In
Além dos benefícios que o WPF adiciona aos comportamentos padrão fornecidos por HwndSource, HwndHost e identificadores de janela, também há limitações para interfaces de utilizador de suplemento que são exibidas a partir de aplicações anfitriãs.
As interfaces de utilizador de suplementos mostradas a partir de uma aplicação anfitriã não respeitam o comportamento de corte da aplicação anfitriã.
O conceito de espaço aéreo em cenários de interoperabilidade também se aplica aos suplementos (ver Descrição geral das regiões tecnológicas).
Os serviços de interface do usuário de um aplicativo host, como herança de recursos, vinculação de dados e comandos, não estão automaticamente acessíveis para interfaces de usuário de extensões. Para fornecer estes serviços ao suplemento, é necessário atualizar o pipeline.
Uma interface de utilizador do suplemento não pode ser girada, dimensionada, distorcida ou afetada por uma transformação (consulte Visão geral das transformações).
O conteúdo dentro das interfaces de usuário do suplemento que é renderizado desenhando operações do System.Drawing namespace pode incluir mistura alfa. No entanto, tanto uma interface do usuário de suplemento quanto a interface do usuário do aplicativo host que a contém devem ser 100% opacas; Em outras palavras, a
Opacitypropriedade em ambos deve ser definida como 1.Se a AllowsTransparency propriedade de uma janela na aplicação anfitriã que contém um suplemento estiver definida como
true, o suplemento ficará invisível. Isso é verdadeiro mesmo se a interface do utilizador do suplemento for opaca a 100%% (ou seja, a propriedadeOpacitytem um valor de 1).Uma interface do complemento deve aparecer sobre outros elementos do WPF na mesma janela de nível superior.
Nenhuma parte da interface do utilizador de um suplemento pode ser renderizada usando um VisualBrush. Em vez disso, o suplemento pode tirar um instantâneo da UI gerada para criar um bitmap que pode ser passado para a aplicação host usando métodos definidos pelo contrato.
Os ficheiros multimédia não podem ser reproduzidos a partir de uma MediaElement IU num suplemento.
Os eventos de mouse gerados para a interface do usuário do suplemento não são recebidos nem gerados pelo aplicativo host, e a propriedade para a interface do
IsMouseOverusuário do aplicativo host tem um valor defalse.Quando o foco muda entre controlos numa interface de utilizador de suplemento, os eventos
GotFocuseLostFocusnão são recebidos nem gerados pelo aplicativo host.A parte de um aplicativo host que contém uma interface do usuário de suplemento aparece em branco quando impressa.
Todos os despachantes (consulte Dispatcher) criados pela interface de utilizador da extensão devem ser desligados manualmente antes que a extensão do proprietário seja descarregada, se a aplicação anfitriã continuar a executar. O contrato pode implementar métodos que permitem que a aplicação anfitriã sinalize o complemento antes de descarregar o complemento, permitindo assim que a interface do utilizador do complemento encerre os seus despachadores.
Se uma UI de suplemento for um InkCanvas ou contiver um InkCanvas, você não poderá desativar o suplemento.
Otimização do Desempenho
Por padrão, quando vários domínios de aplicativo são usados, os vários assemblies do .NET Framework exigidos por cada aplicativo são todos carregados no domínio desse aplicativo. Como resultado, o tempo necessário para criar novos domínios de aplicativo e iniciar aplicativos neles pode afetar o desempenho. No entanto, o .NET Framework fornece uma maneira de reduzir os tempos de início instruindo os aplicativos a compartilhar assemblies entre domínios de aplicativo se eles já estiverem carregados. Você faz isso usando o atributo LoaderOptimizationAttribute , que deve ser aplicado ao método de ponto de entrada (Main). Nesse caso, você deve usar apenas o código para implementar sua definição de aplicativo (consulte Visão geral do gerenciamento de aplicativos).
Ver também
.NET Desktop feedback