Esta documentación está archivada y no tiene mantenimiento.

Información general sobre complementos de Windows Presentation Foundation

Actualización: noviembre 2007

.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.

Es necesario conocer el modelo de complementos de .NET Framework. Para obtener más información, vea Información general sobre complementos.

En este tema se utilizan los ejemplos siguientes para mostrar cómo WPF extiende el modelo de complementos de .NET Framework:

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 Información general sobre 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 generar modelos de complementos.

Nota:

Para obtener información más detallada sobre los complementos, vea Información general sobre complementos.

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 interfaz de usuario para los complementos.

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:

  1. El complemento devuelve una interfaz de usuario. Un complemento devuelve una interfaz de usuario 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 interfaz de usuario devuelta por un complemento depende de los datos o condiciones que solamente existen en tiempo de ejecución, como informes generados dinámicamente.

    • La interfaz de usuario para 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 de su estado a la aplicación host mediante una interfaz de usuario.

  2. El complemento es una interfaz de usuario. Un complemento es una interfaz de usuario, 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 interfaz de usuario 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 interfaz de usuario 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:

Nota:

Para obtener más información sobre la creación de objetos utilizables de forma remota de .NET Framework, vea Hacer que los objetos sean remotos. Para obtener información general sobre la comunicación remota, vea .Información general de comunicación remota de .NET Framework.

Los tipos de interfaz de usuario 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 interfaz de usuario 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:

  1. WPF requiere que las UIs proporcionadas por complementos sean clases que deriven, directa o indirectamente, de FrameworkElement, como formas, controles, controles de usuario, paneles de diseño y páginas.

  2. 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 interfaz de usuario del complemento que se puede pasar más allá de los límites de aislamiento.

  3. Antes de que pase desde el dominio de aplicación del complemento, un objeto FrameworkElement se empaqueta como una interfaz INativeHandleContract llamando a ViewToContractAdapter.

  4. 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.

Para que un complemento devuelva una interfaz de usuario a una aplicación host, se requiere lo siguiente:

  1. La aplicación host, el complemento y la canalización deben crearse de acuerdo con la documentación de .NET Framework Complementos y extensibilidad.

  2. El contrato debe implementar IContract y, para devolver una interfaz de usuario, el contrato debe declarar un método que devuelva un valor de tipo INativeHandleContract.

  3. La interfaz de usuario que se pasa entre el complemento y la aplicación host debe derivarse, directa o indirectamente, de FrameworkElement.

  4. La interfaz de usuario que el complemento devuelve debe convertirse de un objeto FrameworkElement en una interfaz INativeHandleContract antes de cruzar el límite de aislamiento.

  5. La interfaz de usuario que se devuelve debe convertirse de una interfaz INativeHandleContract en un objeto FrameworkElement después de cruzar el límite de aislamiento.

  6. La aplicación host muestra el objeto FrameworkElement devuelto.

Para obtener un ejemplo que muestra cómo implementar un complemento que devuelve una interfaz de usuario, vea Cómo: Crear un complemento que devuelva una interfaz de usuario. Para ver un ejemplo completo, vea Ejemplo Add-In Returns a UI.

Cuando un complemento es una interfaz de usuario, se requiere lo siguiente:

  1. La aplicación host, el complemento y la canalización deben crearse de acuerdo con la documentación de .NET Framework Complementos y extensibilidad.

  2. La interfaz de contrato para el complemento debe implementar INativeHandleContract.

  3. El complemento que se pasa a la aplicación host debe derivar, directa o indirectamente, de FrameworkElement.

  4. El complemento se debe convertir de un objeto FrameworkElement en una interfaz INativeHandleContract antes de cruzar el límite de aislamiento.

  5. El complemento se debe convertir de una interfaz INativeHandleContract en un objeto FrameworkElement después de cruzar el límite de aislamiento.

  6. La aplicación host muestra el objeto FrameworkElement devuelto.

Para obtener un ejemplo que muestra cómo implementar un complemento que devuelve una interfaz de usuario, vea Cómo: Crear un complemento que devuelva una interfaz de usuario. Para ver un ejemplo completo, vea Ejemplo Add-In Is a UI.

Los complementos proporcionan a menudo varias UIs para mostrar aplicaciones host. Por ejemplo, considere un complemento que sea una interfaz de usuario que además proporciona información de estado a la aplicación host, también como una interfaz de usuario. 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.

Para obtener un ejemplo completo que lo ilustra, vea Ejemplo Add-In with Multiple UIs.

Hasta ahora, en los ejemplos, la aplicación host era una aplicación independiente instalada. Sin embargo, las Aplicaciones del explorador XAML (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.

Nota:

Para ver una implementación completa de una aplicación XBAP que hospeda un complemento, vea Ejemplo Add-In with an XBAP as the Host Application.

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 generar la canalización y el ensamblado de complemento en la raíz del proyecto de la aplicación XBAP estableciendo el resultado 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 los resultados 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 los resultados de la compilación

Contrato

..\HostXBAP\Contracts\

Vista de complemento

..\HostXBAP\AddInViews\

Adaptador del complemento

..\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:

  1. 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.

  2. 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:

  1. 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.

  2. 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.

En el nivel más alto, tal y como hemos visto, WPF permite a los complementos de .NET Framework implementar UIs (que 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 interfaz de usuario de la aplicación host.

Para los escenarios simples de complementos de interfaz de usuario, 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 interfaz de usuario para entender sus ventajas y limitaciones.

Fundamentalmente, WPF no pasa una interfaz de usuario de un complemento a una aplicación host; WPF pasa el identificador de ventana Win32 para la interfaz de usuario utilizando la interoperabilidad de WPF. Como tal, cuando se pasa una interfaz de usuario de un complemento a una aplicación host, ocurre lo siguiente:

  • En el lado del complemento, WPF adquiere un identificador de ventana para la interfaz de usuario que la aplicación host mostrará. El identificador de ventana está encapsulado por una clase interna de WPF que 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 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 Información general sobre la interoperabilidad 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 pase de un complemento a una aplicación host, donde es encapsulado por HwndHost y muestra la interfaz de usuario 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.

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 interfaz de usuario de WPF, como el diseño, la representació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 interfaz de usuario de una aplicación host y la interfaz de usuario de un complemento. Observe que el modelo de programación "El complemento es una interfaz de usuario" requiere que el adaptador del complemento 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 interfaz de usuario 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 interfaz de usuario", la única manera de pasar el identificador de ventana para una interfaz de usuario de complemento más allá del límite de aislamiento es llamar a ViewToContractAdapter.

    • Para el modelo de programación "El complemento es una interfaz de usuario", es preciso invalidar QueryContract en el adaptador del complemento y llamar a ViewToContractAdapter (tal como se muestra en los ejemplos anteriores), así como llamar a la implementación de QueryContract del adaptador del complemento 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 interfaz de usuario 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.

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 Interoperabilidad de WPF: Información general sobre "Espacio aéreo" y regiones de ventana).

  • Los servicios de interfaz de usuario 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 interfaz de usuario 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 representa mediante operaciones de dibujo desde el espacio de nombres System.Drawing puede incluir mezclas alfa. Sin embargo, tanto la interfaz de usuario del complemento como la interfaz de usuario 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 interfaz de usuario de complemento está establecida en true, el complemento será invisible. Esto es cierto aunque la interfaz de usuario del complemento sea 100% opaca (es decir, aunque la propiedad Opacity tenga el valor 1).

  • Una interfaz de usuario de complemento debe aparecer encima de los demás elementos de WPF en la misma ventana de nivel superior.

  • Ninguna parte de la interfaz de usuario de un complemento puede representarse 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 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 interfaz de usuario de complemento.

  • Los eventos del mouse generados para la interfaz de usuario del complemento no los recibe ni los provoca la aplicación host, y la propiedad IsMouseOver de la interfaz de usuario de la aplicación host tiene el valor false.

  • Cuando el foco se desplaza entre los controles de una interfaz de usuario 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 interfaz de usuario de complemento aparece en blanco al imprimirse.

  • Todos los distribuidores (vea Dispatcher) creados por la interfaz de usuario 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 interfaz de usuario del complemento cierre sus distribuidores.

  • Si una interfaz de usuario de complemento es un control InkCanvas o contiene un control InkCanvas, no es posible descargar el complemento.

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).

En los ejemplos siguientes, explicados anteriormente, se muestra el uso de LoaderOptimizationAttribute:

Mostrar: