Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
.NET Framework incluye un modelo de complemento que los desarrolladores pueden usar para crear aplicaciones que admitan la extensibilidad del complemento. Este modelo de complemento permite la creación de complementos que se integran con y amplían la funcionalidad de la aplicación. En algunos escenarios, las aplicaciones también deben mostrar las interfaces de usuario que proporcionan los complementos. En este tema se muestra cómo WPF aumenta el modelo de complemento de .NET Framework para habilitar estos escenarios, la arquitectura subyacente, sus ventajas y sus limitaciones.
Prerrequisitos
Es necesario estar familiarizado con el modelo de complemento de .NET Framework. Para obtener más información, vea Complementos y extensibilidad.
Información general de Add-Ins
Para evitar las complejidades de la recompilación y reimplementación de aplicaciones para incorporar nuevas funcionalidades, las aplicaciones implementan mecanismos de extensibilidad que permiten a los desarrolladores (tanto de terceros como de terceros) 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 extensiones (también conocidas como "complementos" y "plugins"). Entre los ejemplos de aplicaciones reales que exponen la extensibilidad con complementos se incluyen:
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 terceros implementar "complementos" que amplían el Reproductor de Windows Media de varias maneras, incluida la creación de descodificadores y codificadores para formatos multimedia que no son compatibles de forma nativa con el Reproductor de Windows Media (por ejemplo, DVD, MP3), efectos de audio y máscaras. Cada modelo de complemento se crea para exponer la funcionalidad única de una aplicación, aunque hay varias entidades y comportamientos comunes a todos los modelos de complemento.
Las tres entidades principales de soluciones de extensibilidad de complementos típicas son contratos, complementos y 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 implementada por las aplicaciones host.
Las aplicaciones host exponen la funcionalidad de los complementos con los que se va a integrar.
Para que se usen complementos, las aplicaciones host deben encontrarlos y cargarlos en tiempo de ejecución. Por lo tanto, las aplicaciones que admiten complementos tienen las siguientes responsabilidades adicionales:
Detección: búsqueda de complementos que cumplen los contratos admitidos por las aplicaciones host.
Activación: carga, ejecución y establecimiento de la comunicación con complementos.
Aislamiento: use 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 complementos.
Comunicación: permitir que los complementos y las aplicaciones host se comuniquen entre sí a través de los límites de aislamiento llamando a métodos y pasando datos.
Administración del ciclo de vida: carga y descarga de dominios y procesos de aplicación de forma limpia y predecible (consulte Dominios de aplicación).
Control de versiones: asegúrese de que las aplicaciones host y los complementos pueden seguir comunicándose cuando se crean nuevas versiones de cualquiera de ellas.
En última instancia, el desarrollo de un modelo de complemento sólido es una tarea que no es simple. Por este motivo, .NET Framework proporciona una infraestructura para compilar modelos de complemento.
Nota:
Para obtener información más detallada sobre los complementos, consulte Complementos y extensibilidad.
Introducción al modelo de Add-In de .NET Framework
El modelo de complemento de .NET Framework, que se encuentra en el System.AddIn espacio de nombres, contiene un conjunto de tipos diseñados para simplificar el desarrollo de la extensibilidad del complemento. La unidad fundamental del modelo de complemento de .NET Framework es el contrato, que define cómo se comunica una aplicación host y un complemento entre sí. Un contrato se expone a una aplicación host mediante una vista específica de la aplicación host del contrato. Del mismo modo, se expone una vista del contrato específica para el complemento. Se usa un adaptador para permitir que una aplicación host y un complemento se comuniquen entre sus respectivas vistas del contrato. Los contratos, las vistas y los adaptadores se conocen como segmentos, y un conjunto de segmentos relacionados constituye un pipeline. Las canalizaciones son la base sobre la que el modelo de complementos del .NET Framework admite la detección, activación, aislamiento de seguridad, aislamiento de ejecución (mediante dominios de aplicación y procesos), comunicación, administración del ciclo de vida y control de versiones.
La suma de esta compatibilidad permite a los desarrolladores compilar complementos que se integran con la funcionalidad de una aplicación host. Sin embargo, algunos escenarios requieren que las aplicaciones host muestren las interfaces de usuario proporcionadas por los complementos. Dado que cada tecnología de presentación de .NET Framework tiene su propio modelo para implementar interfaces de usuario, el modelo de complemento de .NET Framework no admite ninguna tecnología de presentación determinada. En su lugar, WPF extiende el modelo de complementos de .NET Framework con soporte de interfaz para complementos.
Add-Ins de WPF
WPF, junto con el modelo de complemento de .NET Framework, permite abordar una amplia variedad de escenarios que requieren aplicaciones host para mostrar interfaces de usuario desde complementos. En concreto, WPF aborda estos escenarios con los dos modelos de programación siguientes:
El complemento devuelve una interfaz de usuario. Un complemento devuelve una interfaz de usuario a la aplicación host a través de una llamada de método, tal como se define en el contrato. Este escenario se usa en los casos siguientes:
La apariencia de una interfaz de usuario devuelta por un complemento depende de datos o condiciones que solo existen en tiempo de ejecución, como informes generados dinámicamente.
La interfaz de usuario de los servicios proporcionados por un complemento difiere de la interfaz de usuario de las aplicaciones host que pueden usar el complemento.
El complemento realiza principalmente un servicio para la aplicación host e informa del estado a la aplicación host con una interfaz de usuario.
El complemento es una interfaz de usuario. Un complemento es una interfaz de usuario, tal como se define en el contrato. Este escenario se usa en los casos siguientes:
Un complemento no proporciona servicios, aparte de ser mostrado, como un anuncio.
La interfaz de usuario de los servicios proporcionados por un complemento es común a todas las aplicaciones host que pueden usar ese complemento, como una calculadora o un selector de colores.
Estos escenarios requieren que se puedan pasar objetos de interfaz de usuario entre dominios de aplicación host y de aplicación de complemento. Dado que el modelo de complemento de .NET Framework se basa en la comunicación remota para comunicarse entre dominios de aplicación, los objetos que se pasan entre ellos deben ser remotos.
Un objeto remota es una instancia de una clase que realiza una o varias de las siguientes acciones:
Deriva de la MarshalByRefObject clase .
Implementa la interfaz ISerializable.
Tiene aplicado el SerializableAttribute atributo .
Nota:
Para obtener más información sobre la creación de objetos de .NET Framework remotos, vea Hacer remotos objetos.
Los tipos de interfaz de usuario de WPF no son remotos. Para solucionar el problema, WPF amplía el modelo de complemento de .NET Framework para permitir que la interfaz de usuario de WPF creada por complementos se muestre desde aplicaciones host. WPF proporciona esta compatibilidad por dos tipos: la INativeHandleContract interfaz y dos métodos estáticos implementados por la FrameworkElementAdapters clase : ContractToViewAdapter y ViewToContractAdapter. En un nivel alto, estos tipos y métodos se usan de la siguiente manera:
WPF requiere que las interfaces de usuario proporcionadas por los complementos sean clases que derivan 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, debe declararse como ( INativeHandleContract no un FrameworkElement); INativeHandleContract es una representación remota de la interfaz de usuario del complemento que se puede pasar a través de los límites de aislamiento.
Antes de ser pasado desde el dominio de aplicación del complemento, FrameworkElement se empaqueta como INativeHandleContract llamando a ViewToContractAdapter.
Después de pasarse al dominio de aplicación de la aplicación host, INativeHandleContract se debe volver a empaquetar como un FrameworkElement llamando a ContractToViewAdapter.
El modo INativeHandleContracten que se usan , ContractToViewAdaptery ViewToContractAdapter depende del escenario específico. En las secciones siguientes se proporcionan detalles para cada modelo de programación.
Add-In Devuelve una interfaz de usuario
Para que un complemento devuelva una interfaz de usuario a una aplicación host, se requieren lo siguiente:
La aplicación host, el complemento y la canalización deben crearse, tal como se describe en la documentación de complementos y extensibilidad de .NET Framework.
El contrato debe implementar IContract y, para devolver una interfaz de usuario, el contrato debe declarar un método con un valor devuelto de tipo INativeHandleContract.
La interfaz de usuario que se pasa entre el complemento y la aplicación host debe derivar directa o indirectamente de FrameworkElement.
La interfaz de usuario que devuelve el complemento debe convertirse de una FrameworkElement a una INativeHandleContract antes de cruzar el límite de aislamiento.
La interfaz de usuario devuelta debe transformarse de una INativeHandleContract a una FrameworkElement después de cruzar el límite de aislamiento.
La aplicación anfitriona muestra el resultado devuelto FrameworkElement.
Para obtener un ejemplo que muestra cómo implementar un complemento que devuelve una interfaz de usuario, consulte Creación de un Add-In que devuelve una interfaz de usuario.
Add-In es una interfaz de usuario
Cuando un complemento es una interfaz de usuario, se requieren lo siguiente:
La aplicación host, el complemento y la canalización deben crearse, tal como se describe en la documentación de complementos y extensibilidad de .NET Framework.
La interfaz de contrato del complemento debe implementar INativeHandleContract.
El complemento que se pasa a la aplicación host debe derivar directa o indirectamente de FrameworkElement.
El complemento debe convertirse de FrameworkElement a INativeHandleContract antes de cruzar el límite de aislamiento.
El complemento debe convertirse de un INativeHandleContract a un FrameworkElement después de cruzar el límite de aislamiento.
La aplicación anfitriona muestra el resultado devuelto FrameworkElement.
Para obtener un ejemplo de cómo implementar un complemento que es una interfaz de usuario, consulte Crear un Add-In que es una interfaz de usuario.
Devolver varias interfaces de usuario desde un Add-In
Los complementos suelen proporcionar varias interfaces de usuario para que se muestren las aplicaciones host. Por ejemplo, considere un complemento que es una interfaz de usuario que también proporciona información de estado a la aplicación host, también como interfaz de usuario. Un complemento como este se puede implementar mediante una combinación de técnicas de la Add-In Devuelve una interfaz de usuario y Add-In Es un modelo de interfaz de usuario .
Add-Ins y aplicaciones de explorador XAML
En los ejemplos hasta ahora, la aplicación host ha sido una aplicación independiente instalada. Pero las aplicaciones del explorador XAML (XBAPs) también pueden hospedar complementos, aunque con los siguientes requisitos de compilación e implementación adicionales:
El manifiesto de aplicación XBAP debe configurarse especialmente para descargar la canalización (carpetas y ensamblados) y el ensamblado de complemento en la caché de la aplicación ClickOnce en el equipo cliente, en la misma carpeta que el XBAP.
El código XBAP para detectar y cargar complementos debe usar la caché de aplicaciones ClickOnce para XBAP como la canalización y la ubicación del complemento.
El XBAP debe cargar el complemento en un contexto de seguridad especial si el complemento hace referencia a archivos sueltos que se encuentran en el sitio de origen; cuando se hospedan en XBAPs, los complementos solo pueden hacer referencia a archivos sueltos que se encuentran en el sitio de origen de la aplicación host.
Estas tareas se describen en detalle en las siguientes subsecciones.
Configuración del pipeline y Add-In para la implementación de ClickOnce
Los XBAP se descargan y se ejecutan desde una carpeta segura en la caché de implementación de ClickOnce. Para que un XBAP hospede un complemento, la canalización y el ensamblado del complemento igualmente deben descargarse en la carpeta segura. Para ello, debe configurar el manifiesto de aplicación para incluir tanto la canalización como el ensamblado de complemento para su descarga. Esto se hace con mayor facilidad en Visual Studio, aunque la canalización y el ensamblado de complemento deben estar en la carpeta raíz del proyecto XBAP del host para que Visual Studio detecte los ensamblados de canalización.
Por lo tanto, el primer paso es compilar el ensamblaje de la canalización y el ensamblaje adicional en la raíz del proyecto XBAP configurando la salida de compilación de cada proyecto de ensamblaje de la canalización y del ensamblaje adicional. En la tabla siguiente se muestran las rutas de salida de compilación para los proyectos de ensamblado de canalización y el proyecto de ensamblado de complemento que se encuentran en la misma solución y carpeta raíz que el proyecto XBAP de host.
Tabla 1: Rutas de acceso de salida de compilación para los ensamblados de canalización hospedados por un XBAP
| Proyecto de ensamblado de canalización | Ruta de salida de compilación |
|---|---|
| Contrato | ..\HostXBAP\Contracts\ |
| vista de Add-In | ..\HostXBAP\AddInViews\ |
| Añadir adaptadorIn-Side | ..\HostXBAP\AddInSideAdapters\ |
| Adaptador Host-Side | ..\HostXBAP\HostSideAdapters\ |
| Add-In | ..\HostXBAP\AddIns\WPFAddIn1 |
El siguiente paso es especificar los ensamblados de canalización y el ensamblado de complemento como archivos de contenido XBAPs en Visual Studio haciendo lo siguiente:
Para incluir la canalización y el ensamblado de complemento en el proyecto, haga clic con el botón derecho en cada carpeta de canalización en el Explorador de soluciones y elija Incluir en el proyecto.
Establecer la Acción de Compilación de cada ensamblado de la canalización y del complemento en Contenido, desde la ventana Propiedades.
El último paso es configurar el manifiesto de la aplicación para incluir los archivos de ensamblaje de la canalización y el archivo de ensamblaje del complemento para su descarga. Los archivos deben encontrarse en carpetas en la raíz de la carpeta de la caché ClickOnce que ocupa la aplicación XBAP. La configuración se puede lograr en Visual Studio haciendo lo siguiente:
Haga clic con el botón derecho en el proyecto XBAP, haga clic en Propiedades, haga clic en Publicary, 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 Estado de Publicación de cada canalización y DLL de complemento en Incluir (Automático), y establezca el Grupo de Descarga para cada canalización y archivo DLL de complemento en (Obligatorio).
Uso de la canalización y Add-In desde la base de aplicaciones
Cuando la canalización y el complemento están configurados para la implementación de ClickOnce, se descargan en la misma carpeta de caché de ClickOnce que XBAP. Para usar la canalización y el complemento desde XBAP, el código XBAP debe obtenerlos de la base de la aplicación. Los distintos tipos y miembros del modelo de complemento de .NET Framework para usar canalizaciones y complementos proporcionan compatibilidad especial para este escenario. En primer lugar, la ruta se identifica mediante el valor de enumeración ApplicationBase. Este valor se usa con sobrecargas de los miembros de complemento pertinentes para usar canalizaciones que incluyen lo siguiente:
Acceso al sitio de origen del host
Para asegurarse de que un complemento puede hacer referencia a archivos desde el 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 AddInSecurityLevel.Host valor de enumeración y se pasa al Activate método cuando se activa un complemento.
Arquitectura de WPF Add-In
En el nivel más alto, como hemos visto, WPF permite que los complementos de .NET Framework implementen interfaces de usuario (que derivan directa o indirectamente de FrameworkElement) mediante INativeHandleContracty ViewToContractAdapterContractToViewAdapter. El resultado es que se devuelve un FrameworkElement, que se muestra desde la interfaz de usuario en la aplicación host.
Para escenarios de complementos de interfaz de usuario simples, esto es tanto como un desarrollador necesita. Para escenarios más complejos, especialmente aquellos que intentan usar servicios de WPF adicionales, como el diseño, los recursos y el enlace de datos, se necesita información más detallada sobre cómo WPF amplía el modelo de complemento de .NET Framework con compatibilidad con la interfaz de usuario para comprender sus ventajas y limitaciones.
Fundamentalmente, WPF no pasa una interfaz de usuario de un complemento a una aplicación host; en su lugar, WPF pasa el identificador de ventana Win32 para la interfaz de usuario mediante la interoperabilidad de WPF. Por lo tanto, cuando se pasa una interfaz de usuario de un complemento a una aplicación host, se produce lo siguiente:
En el componente adicional, WPF adquiere un identificador de ventana para la interfaz de usuario que mostrará la aplicación anfitriona. El identificador de ventana se encapsula por una clase interna de WPF que deriva de HwndSource e implementa INativeHandleContract. Una instancia de esta clase se devuelve mediante ViewToContractAdapter y se transfiere del 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 empaqueta de nuevo el HwndSource como una clase interna de WPF que deriva de HwndHost y consume INativeHandleContract. Una instancia de esta clase es devuelta por ContractToViewAdapter a la aplicación anfitriona.
HwndHost existe para mostrar interfaces de usuario, identificadas por identificadores de ventana, desde interfaces de usuario de WPF. Para obtener más información, consulte Interoperación de WPF y Win32.
En resumen, INativeHandleContract, ViewToContractAdapter, y ContractToViewAdapter existen para permitir que el identificador de ventana de una interfaz de usuario de WPF se pase de un complemento a una aplicación host, donde se encapsula mediante un HwndHost y muestra la interfaz de usuario de la aplicación host.
Nota:
Dado que la aplicación host obtiene un HwndHost, la aplicación host no puede convertir el objeto devuelto por ContractToViewAdapter al tipo en el que el complemento lo implementa (por ejemplo, un UserControl).
Por su naturaleza, HwndHost tiene ciertas limitaciones que afectan a la forma en que las aplicaciones host pueden usarlas. Sin embargo, WPF amplía HwndHost con diversas capacidades para escenarios de complemento. Estas ventajas y limitaciones se describen a continuación.
Ventajas de WPF Add-In
Dado que las interfaces de usuario de complemento de WPF se muestran desde aplicaciones host mediante una clase interna que deriva de HwndHost, esas interfaces de usuario están limitadas por las capacidades de HwndHost en lo que respecta a los servicios de interfaz de usuario de WPF, como diseño, representación, enlace de datos, estilos, plantillas y recursos. Sin embargo, WPF aumenta su subclase interna HwndHost con funcionalidades adicionales que incluyen lo siguiente:
Tabulación entre la interfaz de usuario de una aplicación host y la interfaz de usuario de un complemento. Tenga en cuenta que el modelo de programación "el complemento es una interfaz de usuario" requiere que el adaptador del lado del complemento invalide QueryContract para habilitar la tabulación, tanto si el complemento es de plena confianza como de confianza parcial.
Respetar los requisitos de accesibilidad para las interfaces de usuario de las extensiones que se muestran en las interfaces de usuario de la aplicación anfitriona.
Permitir que las aplicaciones WPF se ejecuten de forma segura en varios escenarios de dominio de aplicación.
Prevenir el acceso ilegal a los manipuladores de ventana de la interfaz de usuario del complemento cuando los complementos se ejecutan con aislamiento de seguridad (es decir, un espacio aislado de seguridad de confianza parcial). Llamar a ViewToContractAdapter garantiza esta seguridad.
Para el modelo de programación "el complemento devuelve una interfaz de usuario", la única manera de pasar el identificador de ventana de una interfaz de usuario de complemento a través del límite de aislamiento es llamar a ViewToContractAdapter.
Para el modelo de programación "el complemento es una interfaz de usuario", es necesario sobrescribir QueryContract en el adaptador del lado del complemento y llamar a ViewToContractAdapter (como se muestra en los ejemplos anteriores), al igual que llamar a la implementación del
QueryContracten el adaptador del lado del complemento desde el adaptador del lado del host.
Proporcionar protección contra la ejecución de varios dominios de aplicación. Debido a las limitaciones de los dominios de aplicación, las excepciones no controladas que se producen en los dominios de aplicación de los complementos hacen que toda la aplicación se cierre inesperadamente, aunque exista el límite de aislamiento. Sin embargo, WPF y el modelo de complemento de .NET Framework proporcionan una manera sencilla de solucionar este problema y mejorar la estabilidad de la aplicación. Un complemento de WPF que muestra una interfaz de usuario crea un Dispatcher para el subproceso en el que se ejecuta el dominio de aplicación, si la aplicación host es una aplicación WPF. Puede detectar todas las excepciones no controladas que se producen en el dominio de aplicación controlando el UnhandledException evento del complemento Dispatcherde WPF. Puede obtener el Dispatcher de la propiedad CurrentDispatcher.
Limitaciones de WPF Add-In
Además de las ventajas que WPF agrega a los comportamientos predeterminados proporcionados por HwndSource, HwndHost y los identificadores de ventana, también hay limitaciones para las interfaces de usuario de complemento que se muestran desde las aplicaciones host.
Las interfaces de usuario de complemento mostradas desde una aplicación host no respetan el comportamiento de recorte de la aplicación host.
El concepto de espacio aéreo en escenarios de interoperabilidad también se aplica a los complementos (consulte Introducción a las regiones tecnológicas).
Los servicios de interfaz de usuario de una aplicación host, como la herencia de recursos, el enlace de datos y el comando, no están disponibles automáticamente para las interfaces de usuario del complemento. Para proporcionar estos servicios al complemento, debe actualizar la canalización.
Una interfaz de usuario de complemento no se puede girar, escalar, sesgar ni de ninguna otra manera verse afectada por una transformación (consulte Visión general de las transformaciones).
El contenido dentro de las interfaces de usuario del complemento que se representan mediante operaciones de dibujo desde el System.Drawing espacio de nombres puede incluir combinación alfa. Sin embargo, tanto una interfaz de usuario de complemento como la interfaz de usuario de la aplicación host que lo contiene deben ser 100% opaco; es decir, la
Opacitypropiedad de ambos debe establecerse en 1.Si la propiedad AllowsTransparency de una ventana de la aplicación principal que contiene una interfaz de usuario de complemento está establecida en
true, el complemento es invisible. Esto es cierto incluso si la interfaz de usuario del complemento es 100% opaco (es decir, laOpacitypropiedad tiene un valor de 1).Una interfaz de usuario de complemento debe aparecer encima de otros elementos de WPF en la misma ventana de nivel superior.
No se puede representar ninguna parte de la interfaz de usuario de un complemento mediante .VisualBrush En su lugar, el complemento puede tomar una instantánea de la interfaz de usuario generada para crear un mapa de bits que se pueda pasar a la aplicación host mediante métodos definidos por el contrato.
Los archivos multimedia no se pueden reproducir desde en una MediaElement interfaz de usuario de complemento.
Los eventos del mouse generados para la interfaz de usuario del complemento no se reciben ni generan en la aplicación host, y la propiedad de la
IsMouseOverinterfaz de usuario de la aplicación host tiene un valor defalse.Cuando el foco cambia entre los controles en una interfaz de usuario de complemento, la aplicación anfitriona no recibe ni genera los eventos
GotFocusyLostFocus.La parte de una aplicación host que contiene una interfaz de usuario de complemento aparece blanca cuando se imprime.
Todos los distribuidores (consulte Dispatcher) creados por la interfaz de usuario del complemento deben apagarse manualmente antes de que el complemento propietario se descargue si la aplicación host continúa la ejecución. El contrato puede implementar métodos que permitan a la aplicación anfitriona notificar al complemento antes de desactivar el complemento, lo que permite que la interfaz de usuario del complemento apague sus despachadores.
Si una interfaz de usuario de complemento es un InkCanvas o contiene un InkCanvas, no puede descargar el complemento.
Optimización del rendimiento
De forma predeterminada, cuando se usan varios dominios de aplicación, todos los distintos ensamblados de .NET Framework requeridos por cada aplicación se cargan en el dominio de esa aplicación. Como resultado, el tiempo necesario para crear nuevos dominios de aplicación e iniciar aplicaciones en ellos podría afectar al rendimiento. Sin embargo, .NET Framework proporciona una manera de reducir las horas de inicio al indicar a las aplicaciones que compartan ensamblados entre dominios de aplicación si ya están cargados. Para ello, use el LoaderOptimizationAttribute atributo , que se debe aplicar al método de punto de entrada (Main). En este caso, solo debe usar código para implementar la definición de la aplicación (consulte Introducción a la administración de aplicaciones).
Consulte también
.NET Desktop feedback