Información general sobre los complementos de WPF
.NET Framework incluye un modelo de complementos que los desarrolladores pueden utilizar para crear aplicaciones que admitan la extensibilidad de los complementos. Este modelo de complementos permite la creación de complementos que se integran con la funcionalidad de la aplicación y la extienden. En algunos escenarios, las aplicaciones también necesitan mostrar las UIs proporcionadas por los complementos. En este tema se muestra cómo WPF aumenta el modelo de complementos de .NET Framework para permitir estos escenarios, la arquitectura subyacente, sus ventajas y sus limitaciones.
Este tema contiene las secciones siguientes.
- Requisitos previos
- Información general sobre los complementos
- Información general sobre el modelo de complementos de .NET Framework
- Complementos de WPF
- El complemento devuelve una interfaz de usuario
- El complemento es una interfaz de usuario
- Devolver varias interfaces de usuario de un complemento
- Complementos y aplicaciones de explorador XAML
- Arquitectura de complementos de WPF
- Ventajas de los complementos de WPF
- Limitaciones de los complementos de WPF
- Optimización del rendimiento
- Temas relacionados
Requisitos previos
Es necesario conocer el modelo de complementos de .NET Framework. Para obtener más información, vea Complementos y extensibilidad.
Información general sobre los complementos
Para evitar las complejidades que implican las acciones de compilar e implementar de nuevo una aplicación para que incorpore nuevas funcionalidades, las aplicaciones implementan mecanismos de extensibilidad que permiten a los desarrolladores (tanto propios como de otros fabricantes) crear otras aplicaciones que se integren con ellas. La manera más común de admitir este tipo de extensibilidad es mediante el uso de complementos. Algunos ejemplos de aplicaciones reales que exponen la extensibilidad con complementos son los siguientes:
Complementos de Internet Explorer.
Complementos del Reproductor de Windows Media.
Complementos de Visual Studio.
Por ejemplo, el modelo de complementos del Reproductor de Windows Media permite a los desarrolladores de otros fabricantes implementar complementos que extienden el Reproductor de Windows Media de diversas maneras, entre las que están la creación de descodificadores y codificadores para los formatos multimedia que el Reproductor de Windows Media no admite de forma nativa (por ejemplo, DVD y MP3), efectos de audio y máscaras. Cada modelo de complementos se ha generado de modo que exponga la funcionalidad que es única de una aplicación, aunque hay varias entidades y comportamientos que son comunes a todos los modelos de complementos.
Las tres entidades principales de las típicas soluciones de extensibilidad mediante complementos son los contratos, los complementos y las aplicaciones host. Los contratos definen cómo se integran los complementos con las aplicaciones host de dos maneras:
Los complementos se integran con la funcionalidad que implementan las aplicaciones host.
Las aplicaciones host exponen la funcionalidad para los complementos con los que se integran.
Para poder utilizar complementos, las aplicaciones host deben encontrarlos y cargarlos en tiempo de ejecución. Por consiguiente, las aplicaciones que admiten complementos tienen las siguientes responsabilidades adicionales:
Detección: búsqueda de complementos que se adhieran a los contratos admitidos por las aplicaciones host.
Activación: carga, ejecución y establecimiento de la comunicación con los complementos.
Aislamiento: uso de dominios de aplicación o procesos para establecer límites de aislamiento que protejan las aplicaciones frente a posibles problemas de seguridad y ejecución con los complementos.
Comunicación: los complementos y las aplicaciones host deben poder comunicarse entre sí más allá de los límites de aislamiento llamando a métodos y pasando datos.
Administración de la duración: carga y descarga de los dominios de aplicación y procesos de una manera limpia y predecible (vea Dominios de aplicación).
Control de versiones: garantía de que las aplicaciones host y los complementos puedan continuar comunicándose cuando se creen nuevas versiones de cualquiera de ellos.
En última instancia, el desarrollo de un modelo de complementos robusto no es una tarea trivial. Por esta razón, .NET Framework proporciona una infraestructura para compilar modelos de complementos.
Nota |
---|
Para obtener información más detallada sobre los complementos, vea Complementos y extensibilidad. |
Información general sobre el modelo de complementos de .NET Framework
El modelo de complementos de .NET Framework, que se encuentra en el espacio de nombres System.AddIn, contiene un conjunto de tipos que permiten simplificar el desarrollo de la extensibilidad mediante complementos. La unidad fundamental del modelo de complementos de .NET Framework es el contrato, que define cómo se comunican entre sí una aplicación host y un complemento. Un contrato se expone a una aplicación host utilizando una vista del contrato que es específica de la aplicación host. De manera similar, se expone al complemento una vista del contrato que es específica del complemento. Se utiliza un adaptador para que una aplicación host y un complemento puedan comunicarse entre sus respectivas vistas del contrato. Los contratos, las vistas y los adaptadores se conocen como segmentos y un conjunto de segmentos relacionados constituye una canalización. Las canalizaciones son la base para que el modelo de complementos de .NET Framework admita la detección, la activación, el aislamiento de seguridad, el aislamiento de ejecución (utilizando tanto dominios de aplicación como procesos), la comunicación, la administración de la duración y el control de versiones.
La suma de estas compatibilidades permite a los desarrolladores generar complementos que se integran con la funcionalidad de una aplicación host. Sin embargo, algunos escenarios requieren que las aplicaciones host muestren las UIs proporcionadas por los complementos. Dado que cada tecnología de presentación de .NET Framework tiene su propio modelo para implementar las UIs, el modelo de complementos de .NET Framework no es compatible con ninguna tecnología de presentación en particular. En su lugar, WPF extiende el modelo de complementos de .NET Framework con la compatibilidad de UI para los complementos.
Complementos de WPF
WPF, junto con el modelo de complementos de .NET Framework, permite manejar una amplia variedad de escenarios que requieren que las aplicaciones host muestren las UIs de los complementos. En concreto, WPF maneja estos escenarios con estos dos modelos de programación:
El complemento devuelve una interfaz de usuario. Un complemento devuelve una UI a la aplicación host mediante una llamada de método, que se define en el contrato. Este escenario se utiliza en los casos siguientes:
La apariencia de una UI devuelta por un complemento depende de los datos o condiciones que solamente existen en tiempo de ejecución, como informes generados dinámicamente.
La UI para los servicios proporcionados por un complemento difiere de la UI de las aplicaciones host que pueden usar el complemento.
El complemento realiza principalmente un servicio para la aplicación host e informa de su estado a la aplicación host mediante una UI.
El complemento es una interfaz de usuario. Un complemento es una UI, tal como lo define el contrato. Este escenario se utiliza en los casos siguientes:
Un complemento no proporciona más servicios que el de mostrarse, como un anuncio.
La UI para los servicios proporcionados por un complemento es común a todas las aplicaciones host que pueden utilizar ese complemento, como una calculadora o un selector de color.
Estos escenarios requieren que se puedan pasar los objetos de la UI entre la aplicación host y los dominios de aplicación del complemento. Puesto que el modelo de complementos de .NET Framework se basa en la comunicación remota para establecer la comunicación entre los dominios de aplicación, los objetos que se pasen entre ellos deberán poder usarse de forma remota.
Un objeto utilizable de forma remota es una instancia de una clase que cumple una o varias de las siguientes condiciones:
Deriva de la clase MarshalByRefObject.
Implementa la interfaz ISerializable.
Tiene aplicado el atributo SerializableAttribute.
Nota |
---|
Para obtener más información sobre la creación de objetos utilizables de forma remota de .NET Framework, vea Making Objects Remotable. |
Los tipos de UI de WPF no se pueden usar de forma remota. Para resolver el problema, WPF extiende el modelo de complementos de .NET Framework para permitir que la UI de WPF creada por complementos se muestre desde las aplicaciones host. Esta compatibilidad la proporciona WPF mediante dos tipos: la interfaz INativeHandleContract y dos métodos estáticos que se implementan mediante la clase FrameworkElementAdapters: ContractToViewAdapter y ViewToContractAdapter. A alto nivel, estos tipos y métodos se utilizan de la manera siguiente:
WPF requiere que las UIs proporcionadas por complementos sean clases que se deriven, directa o indirectamente, de FrameworkElement, como formas, controles, controles de usuario, paneles de diseño y páginas.
Siempre que el contrato declare que se pasará una interfaz de usuario entre el complemento y la aplicación host, ésta debe declararse como una interfaz INativeHandleContract (en lugar de un objeto FrameworkElement);INativeHandleContract es una representación utilizable de forma remota de la UI del complemento que se puede pasar más allá de los límites de aislamiento.
Antes de que pase desde el dominio de aplicación del complemento, un objeto FrameworkElement se empaqueta como una interfaz INativeHandleContract llamando a ViewToContractAdapter.
Después de pasar al dominio de aplicación de la aplicación host, la interfaz INativeHandleContract debe volver a empaquetarse como un objeto FrameworkElement llamando a ContractToViewAdapter.
Cómo se utilicen INativeHandleContract, ContractToViewAdapter y ViewToContractAdapter depende del escenario en cuestión. En las secciones siguientes se proporciona información detallada para cada modelo de programación.
El complemento devuelve una interfaz de usuario
Para que un complemento devuelva una UI a una aplicación host, se requiere lo siguiente:
La aplicación host, el complemento y la canalización deben crearse de acuerdo con la documentación de .NET Framework Complementos y extensibilidad.
El contrato debe implementar IContract y, para devolver una UI, el contrato debe declarar un método que devuelva un valor de tipo INativeHandleContract.
La UI que se pasa entre el complemento y la aplicación host debe derivarse, directa o indirectamente, de FrameworkElement.
La UI que el complemento devuelve debe convertirse de un objeto FrameworkElement en una interfaz INativeHandleContract antes de cruzar el límite de aislamiento.
La UI que se devuelve debe convertirse de una interfaz INativeHandleContract en un objeto FrameworkElement después de cruzar el límite de aislamiento.
La aplicación host muestra el objeto FrameworkElement devuelto.
Para obtener un ejemplo que muestra cómo implementar un complemento que devuelve una UI, vea Cómo: Crear un complemento que devuelva una interfaz de usuario.
El complemento es una interfaz de usuario
Cuando un complemento es una UI, se requiere lo siguiente:
La aplicación host, el complemento y la canalización deben crearse de acuerdo con la documentación de .NET Framework Complementos y extensibilidad.
La interfaz de contrato para el complemento debe implementar INativeHandleContract.
El complemento que se pasa a la aplicación host debe derivar, directa o indirectamente, de FrameworkElement.
El complemento se debe convertir de un objeto FrameworkElement en una interfaz INativeHandleContract antes de cruzar el límite de aislamiento.
El complemento se debe convertir de una interfaz INativeHandleContract en un objeto FrameworkElement después de cruzar el límite de aislamiento.
La aplicación host muestra el objeto FrameworkElement devuelto.
Para obtener un ejemplo en el que se muestra cómo implementar un complemento que es una UI, vea Cómo: Crear un complemento que sea una interfaz de usuario.
Devolver varias interfaces de usuario de un complemento
Los complementos proporcionan a menudo varias UIs para mostrar aplicaciones host. Por ejemplo, considere un complemento que sea una UI que además proporciona información de estado a la aplicación host, también como una UI. Un complemento de este tipo se puede implementar mediante una combinación de técnicas de los modelos El complemento devuelve una interfaz de usuario y El complemento es una interfaz de usuario.
Complementos y aplicaciones de explorador XAML
Hasta ahora, en los ejemplos, la aplicación host era una aplicación independiente instalada. Sin embargo, las XAML browser applications (XBAPs) también pueden hospedar complementos, aunque con los siguientes requisitos adicionales de compilación e implementación:
El manifiesto de aplicación XBAP se debe configurar especialmente para descargar la canalización (carpetas y ensamblados) y el ensamblado de complemento en la memoria caché de aplicación de ClickOnce del equipo cliente, en la misma carpeta que la aplicación XBAP.
El código de la aplicación XBAP para detectar y cargar los complementos debe usar la memoria caché de aplicación de ClickOnce para la aplicación XBAP como ubicación de la canalización y del complemento.
La aplicación XBAP debe cargar el complemento en un contexto de seguridad especial si el complemento hace referencia a archivos separados que están ubicados en el sitio de origen; cuando se hospedan en XBAPs, los complementos solamente pueden hacer referencia a archivos separados que se encuentran en el sitio de origen de la aplicación host.
Estas tareas se describen detalladamente en las siguientes subsecciones.
Configurar la canalización y el complemento para la implementación de ClickOnce
Las XBAPs se descargan y se ejecutan en una carpeta segura en la memoria caché de implementación de ClickOnce. Para que una aplicación XBAP pueda hospedar un complemento, la canalización y el ensamblado de complemento también se deben descargar en la carpeta segura. Para ello, se debe configurar el manifiesto de aplicación de modo que incluya tanto la canalización como el ensamblado de complemento para la descarga. Esto se hace fácilmente en Visual Studio, aunque la canalización y el ensamblado de complemento deben estar en la carpeta raíz del proyecto de la aplicación XBAP host para que Visual Studio detecte los ensamblados de canalización.
Por consiguiente, el primer paso es compilar la canalización y el ensamblado de complemento en la raíz del proyecto de la aplicación XBAP estableciendo la salida de la compilación de cada ensamblado de canalización y proyecto de ensamblado de complemento. En la tabla siguiente, se muestran las rutas de acceso de la salida de la compilación para los proyectos de ensamblado de canalización y el proyecto de ensamblado de complemento que están en la misma solución y en la misma carpeta raíz que el proyecto de la aplicación XBAP host.
Tabla 1: rutas de acceso de los resultados de compilación para los ensamblados de canalización hospedados por una XBAP
Proyecto de ensamblado de canalización |
Ruta de acceso de salida de la compilación |
---|---|
Contrato |
.. \HostXBAP\Contracts\ |
Vista de complemento |
.. \HostXBAP\AddInViews\ |
Adaptador de conversión |
.. \HostXBAP\AddInSideAdapters\ |
Adaptador del host |
.. \HostXBAP\HostSideAdapters\ |
Complemento |
.. \HostXBAP\AddIns\WPFAddIn1 |
El paso siguiente es especificar los ensamblados de canalización y el ensamblado de complemento como archivos de contenido de las XBAPs en Visual Studio; para ello, siga este procedimiento:
Incluya el ensamblado de canalización y el ensamblado de complemento en el proyecto haciendo clic con el botón secundario del mouse en cada carpeta de canalización del Explorador de soluciones y, a continuación, elija Incluir en el proyecto.
Establezca el valor de Acción de compilación de cada ensamblado de canalización y ensamblado de complemento en Contenido en la ventana Propiedades.
El paso final es configurar el manifiesto de aplicación de modo que incluya los archivos de ensamblado de canalización y el archivo de ensamblado de complemento para la descarga. Los archivos deben ubicarse en carpetas en la raíz de la carpeta de la memoria caché de ClickOnce que la aplicación XBAP ocupa. La configuración se puede realizar en Visual Studio siguiendo este procedimiento:
Haga clic con el botón secundario del mouse en el proyecto XBAP, haga clic en Propiedades, haga clic en Publicar y, a continuación, haga clic en el botón Archivos de aplicación.
En el cuadro de diálogo Archivos de aplicación, establezca el valor de Estado de la publicación de cada DLL de canalización y de complemento en Incluir (automático) y establezca el valor de Grupo de descarga para cada DLL de canalización y de complemento en (Requerido).
Utilizar la canalización y el complemento de la base de la aplicación
Cuando la canalización y el complemento se configuran para la implementación de ClickOnce, se descargan en la misma carpeta de la memoria caché de ClickOnce que la aplicación XBAP. Para utilizar la canalización y el complemento de la aplicación XBAP, el código de la aplicación XBAP debe obtenerlos de la base de la aplicación. Los diversos tipos y miembros del modelo de complementos de .NET Framework para el uso de canalizaciones y complementos proporcionan una compatibilidad especial para este escenario. En primer lugar, se identifica la ruta de acceso mediante el valor de enumeración ApplicationBase. Este valor se utiliza con sobrecargas de los miembros pertinentes del complemento para el uso de canalizaciones que incluyan lo siguiente:
Obtener acceso al sitio de origen del host
Para asegurarse de que un complemento pueda hacer referencia a los archivos del sitio de origen, el complemento debe cargarse con aislamiento de seguridad equivalente a la aplicación host. Este nivel de seguridad se identifica mediante el valor de enumeración AddInSecurityLevel.Host y se pasa al método Activate cuando se activa un complemento.
Arquitectura de complementos de WPF
En el nivel más alto, tal y como hemos visto, WPF permite a los complementos de .NET Framework implementar UIs (que se derivan, directa o indirectamente, de FrameworkElement) mediante los métodos INativeHandleContract, ViewToContractAdapter y ContractToViewAdapter. El resultado es que a la aplicación host se le devuelve un objeto FrameworkElement que se muestra en la UI de la aplicación host.
Para los escenarios simples de complementos de UI, esta es toda la información que necesita el desarrollador. Para los escenarios más complejos, en particular aquéllos en los que se intenten utilizar servicios adicionales de WPF como el diseño, los recursos y el enlace de datos, se requieren conocimientos más detallados de cómo WPF extiende el modelo de complementos de .NET Framework con compatibilidad de UI para entender sus ventajas y limitaciones.
Fundamentalmente, WPF no pasa una UI de un complemento a una aplicación host; WPF pasa el identificador de ventana Win32 para la UI utilizando la interoperabilidad de WPF. Como tal, cuando se pasa una UI de un complemento a una aplicación host, ocurre lo siguiente:
En el lado del complemento, WPF adquiere un identificador de ventana para la UI que la aplicación host mostrará. El identificador de ventana está encapsulado por una clase interna de WPF que se deriva de HwndSource e implementa INativeHandleContract. ViewToContractAdapter devuelve una instancia de esta clase y se calculan sus referencias desde el dominio de aplicación del complemento al dominio de aplicación de la aplicación host.
En el lado de la aplicación host, WPF reempaqueta HwndSource como una clase interna de WPF que se deriva de HwndHost y consume INativeHandleContract. ContractToViewAdapter devuelve una instancia de esta clase a la aplicación host.
HwndHost existe para mostrar las UIs, identificadas por identificadores de ventana, desde las UIs de WPF. Para obtener más información, vea Interoperabilidad de WPF y Win32.
En resumen, INativeHandleContract, ViewToContractAdapter y ContractToViewAdapter existen para permitir que el identificador de ventana de una UI de WPF pase de un complemento a una aplicación host, donde es encapsulado por HwndHost y muestra la UI de la aplicación.
Nota |
---|
Dado que la aplicación host obtiene una clase HwndHost, no puede convertir el objeto devuelto por ContractToViewAdapter en el tipo implementado por el complemento (por ejemplo, un control UserControl). |
Debido a su naturaleza, la clase HwndHost tiene ciertas limitaciones que afectan al modo en que las aplicaciones host la usan. Sin embargo, WPF extiende HwndHost con varias funciones para los escenarios de complementos. Estas ventajas y limitaciones se describen a continuación.
Ventajas de los complementos de WPF
Dado que las UIs de los complementos de WPF se muestran en las aplicaciones host utilizando una clase interna que deriva de HwndHost, esas UIs están restringidas por las funciones de HwndHost respecto a los servicios de la UI de WPF, como el diseño, la presentación, el enlace de datos, los estilos, las plantillas y los recursos. Sin embargo, WPF aumenta su subclase HwndHost interna con funciones adicionales que incluyen las siguientes:
Tabulación entre la UI de una aplicación host y la UI de un complemento. Observe que el modelo de programación "El complemento es una UI" requiere que el adaptador de conversión invalide QueryContract para permitir la tabulación, independientemente de si el complemento es de plena confianza o de confianza parcial.
Cumplimiento de los requisitos de accesibilidad para las UIs de los complementos que se muestran desde las UIs de la aplicación host.
Posibilidad de que las aplicaciones de WPF se ejecuten de forma segura en varios escenarios de dominio de aplicación.
Prevención del acceso ilegal a los identificadores de ventana de la UI de los complementos cuando éstos se ejecutan con aislamiento de seguridad (es decir, un recinto de seguridad de confianza parcial). Al llamar a ViewToContractAdapter, se garantiza esta seguridad:
Para el modelo de programación "El complemento devuelve una UI", la única manera de pasar el identificador de ventana para una UI de complemento más allá del límite de aislamiento es llamar a ViewToContractAdapter.
Para el modelo de programación "El complemento es una UI", es preciso invalidar QueryContract en el adaptador de conversión y llamar a ViewToContractAdapter (tal como se muestra en los ejemplos anteriores), así como llamar a la implementación de QueryContract del adaptador de conversión desde el adaptador del host.
Provisión de protección de ejecución en varios dominios de aplicación. Debido a las limitaciones con los dominios de aplicación, las excepciones no controladas que se producen en los dominios de aplicación del complemento hacen que se bloquee la aplicación completa, aunque exista el límite de aislamiento. Sin embargo, WPF y el modelo de complementos de .NET Framework proporcionan una manera simple de evitar este problema y mejorar la estabilidad de la aplicación. Un complemento de WPF que muestre una UI crea un objeto Dispatcher para el subproceso en el que se ejecuta el dominio de aplicación si la aplicación host es una aplicación de WPF. Para detectar todas las excepciones no controladas que se produzcan en el dominio de aplicación, controle el evento UnhandledException del objeto Dispatcher del complemento de WPF. Puede obtener el objeto Dispatcher mediante la propiedad CurrentDispatcher.
Limitaciones de los complementos de WPF
Más allá de las ventajas que WPF agrega a los comportamientos predeterminados que HwndSource, HwndHost y los identificadores de ventana proporcionan, también hay limitaciones para las UIs de complementos que se muestran desde aplicaciones host:
Las UIs de complementos que se muestran desde una aplicación host no respetan el comportamiento de recorte de la aplicación host.
El concepto de espacio aéreo en los escenarios de interoperabilidad también se aplica a los complementos (vea Información general sobre áreas de la tecnología).
Los servicios de UI de una aplicación host, como la herencia de recursos, el enlace de datos y los comandos, no están disponibles automáticamente para las UIs de los complementos. Para proporcionar estos servicios al complemento, es preciso actualizar la canalización.
Una UI de complemento no se puede girar, escalar, sesgar ni transformar de ninguna otra manera (vea Información general sobre transformaciones).
El contenido de las UIs de complementos que se presenta mediante operaciones de dibujo desde el espacio de nombres System.Drawing puede incluir mezclas alfa. Sin embargo, tanto la UI del complemento como la UI de la aplicación host que la contiene deben ser 100% opacas; en otras palabras, la propiedad Opacity de ambas interfaces debe estar establecida en 1.
Si la propiedad AllowsTransparency de una ventana en la aplicación host que contiene una UI de complemento está establecida en true, el complemento será invisible. Esto es cierto aunque la UI del complemento sea 100% opaca (es decir, aunque la propiedad Opacity tenga el valor 1).
Una UI de complemento debe aparecer encima de los demás elementos de WPF en la misma ventana de nivel superior.
Ninguna parte de la UI de un complemento puede representarse mediante VisualBrush. En su lugar, el complemento puede tomar una instantánea de la UI generada para crear un mapa de bits que se puede pasar a la aplicación host mediante los métodos definidos por el contrato.
No es posible reproducir archivos multimedia desde un control MediaElement en una UI de complemento.
Los eventos del mouse generados para la UI del complemento no los recibe ni los provoca la aplicación host, y la propiedad IsMouseOver de la UI de la aplicación host tiene el valor false.
Cuando el foco se desplaza entre los controles de una UI de complemento, la aplicación host no recibe ni provoca los eventos GotFocus y LostFocus.
La parte de una aplicación host que contiene una UI de complemento aparece en blanco al imprimirse.
Todos los distribuidores (vea Dispatcher) creados por la UI del complemento se deben cerrar manualmente antes de descargar el complemento propietario si la aplicación host continúa ejecutándose. El contrato puede implementar métodos que permiten a la aplicación host señalar el complemento antes de que éste se descargue, permitiendo que la UI del complemento cierre sus distribuidores.
Si una UI de complemento es un control InkCanvas o contiene un control InkCanvas, no es posible descargar el complemento.
Optimización del rendimiento
De forma predeterminada, cuando se utilizan varios dominios de aplicación, los diversos ensamblados de .NET Framework requeridos por cada aplicación se cargan en el dominio de esa aplicación. Como resultado, el tiempo requerido para crear nuevos dominios de aplicación e iniciar aplicaciones en ellos puede afectar al rendimiento. Sin embargo, .NET Framework proporciona un método para reducir los tiempos de inicio indicando a las aplicaciones que compartan los ensamblados en los diversos dominios de aplicación si ya están cargados. Para ello, utilice el atributo LoaderOptimizationAttribute, que debe aplicarse al método de punto de entrada (Main). En este caso, sólo debe utilizar código para implementar la definición de la aplicación (vea Información general sobre la administración de aplicaciones).