Tutorial: Habilitar la compatibilidad con versiones anteriores al cambiar el host

Actualización: Julio de 2008

En este tutorial se describe la versión 2 de la canalización que se explica en Tutorial: Crear una aplicación extensible. La versión 2 incluye características de cálculo adicionales mediante una cadena de operaciones aritméticas separadas por comas que es compatible con el host. El host puede elegir una operación y enviar una ecuación para que el complemento la calcule.

La canalización tiene un nuevo host y un nuevo contrato. Para permitir que la versión 1 del complemento funcione con un nuevo host y un nuevo contrato, la canalización incluye la vista de complemento que se utiliza en la versión 1 y un adaptador del complemento que convierte los datos de la vista de complemento anterior al nuevo contrato. En la ilustración siguiente se muestra cómo los dos complementos pueden trabajar con el mismo host.

Host nuevo, complementos antiguos

Esta canalización también se describe en Escenarios de canalizaciones de complementos.

En este tutorial se describen las tareas siguientes:

  • Crear una solución de Visual Studio.

  • Crear la estructura de directorios de canalización.

  • Crear el contrato y las vistas.

  • Crear el adaptador del complemento, que incluye los adaptadores para la nueva versión y la versión 1 del complemento.

  • Crear el adaptador del host.

  • Crear el host.

  • Crear el complemento.

  • Implementar la canalización.

  • Ejecutar la aplicación host.

En el tutorial también se describe cómo se utilizan las clases base abstractas para definir vistas y se muestra cómo estas vistas son compatibles con las vistas que se definen mediante interfaces. Se recomienda utilizar las interfaces.

Nota:

Parte del código que se incluye en este tutorial contiene referencias a espacios de nombres poco comunes. En los pasos del tutorial se reflejan exactamente las referencias que son necesarias en Visual Studio.

Puede encontrar más código de ejemplo y vistas previas de herramientas con la tecnología de clientes para generar canalizaciones de complementos en el sitio Managed Extensibility and Add-In Framework de CodePlex.

Requisitos previos

Necesita los componentes siguientes para completar este tutorial:

  • Visual Studio.

  • La versión 1 de la canalización se describe en Tutorial: Crear una aplicación extensible. Dado que la versión 2 utiliza segmentos de la canalización que se desarrollaron en la versión 1, debe desarrollar e implementar la versión 1 de la canalización antes de llevar a cabo los pasos que se explican en este tema.

Crear una solución de Visual Studio

Utilice una solución de Visual Studio que contenga los proyectos de sus segmentos de canalización.

Para crear la solución de canalización

  1. En Visual Studio, cree un nuevo proyecto denominado Calc2Contract. Utilice como base la plantilla Biblioteca de clases.

  2. Llame a la solución CalculatorV2.

Crear la estructura de directorios de canalización

El modelo de complementos requiere que los ensamblados de los segmentos de canalización se sitúen en una estructura de directorios específica.

Para crear la estructura de directorios de canalización

  • Si aún no lo ha hecho, agregue la carpeta CalcV2 a la estructura de carpetas de la canalización que creó en Tutorial: Crear una aplicación extensible. La carpeta CalcV2 contendrá la nueva versión del complemento.

    Pipeline
      AddIns
        CalcV1
        CalcV2
      AddInSideAdapters
      AddInViews
      Contracts
      HostSideAdapters
    

    No es necesario que sitúe la estructura de carpetas de la canalización en la carpeta de la aplicación; la única finalidad de hacerlo es facilitar su uso en estos tutoriales. Si en el primer tutorial situó la estructura de carpetas de la canalización en una ubicación diferente, siga el mismo patrón en este tutorial. Vea los comentarios sobre los requisitos de los directorios de la canalización en Requisitos del desarrollo de canalizaciones.

Crear el contrato y las vistas

El segmento del contrato de esta canalización define la interfaz ICalc2Contract, que tiene los dos métodos siguientes:

  • El método GetAvailableOperations.

    Este método devuelve una cadena con las operaciones matemáticas admitidas por el complemento en este host. La versión 2 admite cinco operaciones y este método devuelve la cadena "+,-,*,/,**", donde "**" representa la operación Pow.

    En las vistas de host y de complemento, este método se denomina Operations en lugar de GetAvailableOperations.

    Puede exponer los métodos en el contrato como propiedades de las vistas; para ello, convierta la llamada al método en una propiedad del adaptador.

  • El método Operate.

    El host llama a este método para enviar una ecuación al complemento con el fin de que calcule y devuelva el resultado.

Para crear el contrato

  1. En la solución de Visual Studio denominada CalculatorV2, abra el proyecto Calc2Contract.

  2. En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto Calc2Contract:

    System.AddIn.Contract.dll

    System.AddIn.dll

  3. En el Explorador de soluciones, excluya la clase predeterminada que se agrega a los nuevos proyectos de Biblioteca de clases.

  4. Agregue un nuevo elemento al proyecto utilizando la plantilla Interfaz. En el cuadro de diálogo Agregar nuevo elemento, denomine la interfaz ICalc2Contract.

  5. En el archivo de interfaz, agregue referencias de espacio de nombres a System.AddIn.Contract y System.AddIn.Pipeline.

  6. Utilice el código siguiente para completar el segmento del contrato. Tenga en cuenta que esta interfaz debe tener el atributo AddInContractAttribute.

    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.AddIn.Contract
    Imports System.AddIn.Pipeline
    
    Namespace CalculatorContracts
        <AddInContract()> _
        Public Interface ICalc2Contract
            Inherits IContract
            Function GetAvailableOperations() As String
            Function Operate(ByVal operation As String, ByVal a As Double, ByVal b As Double) As Double
        End Interface
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.AddIn.Contract;
    using System.AddIn.Pipeline;
    
    namespace CalculatorContracts
    {
        [AddInContract]
        public interface ICalc2Contract : IContract
        {      
            string GetAvailableOperations();
            double Operate(String operation, double a, double b);
        }
    }
    

Dado que la vista de complemento y la vista de host tienen el mismo código, resulta sencillo crearlas al mismo tiempo. Sólo se diferencian en un aspecto: la vista de complemento requiere el atributo AddInBaseAttribute, mientras que la vista de host del complemento no requiere ningún atributo.

Para crear la vista de complemento en la versión 2

  1. Agregue un nuevo proyecto denominado Calc2AddInView a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.

  2. En el Explorador de soluciones, agregue una referencia de System.AddIn.dll al proyecto Calc2AddInView.

  3. Cambie el nombre de la clase por Calculator2.

  4. En el archivo de clase, agregue una referencia de espacio de nombres a System.AddIn.Pipeline.

  5. Convierta Calculator2 en una clase abstract (una clase MustInherit en Visual Basic).

  6. Utilice el código siguiente para esta vista de complemento. Tenga en cuenta que esta clase debe tener el atributo AddInBaseAttribute.

    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.AddIn.Pipeline
    
    Namespace CalcAddInViews
        <AddInBase()> _
        Public MustInherit Class Calculator2
            Public MustOverride ReadOnly Property Operations() As String
    
            Public MustOverride Function Operate(ByVal operation As String, ByVal a As Double, ByVal b As Double) As Double
        End Class
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.AddIn.Pipeline;
    
    namespace CalcAddInViews
    {
        [AddInBase]
        public abstract class Calculator2
        {
            public abstract string Operations
            {
                get;
            }
    
            public abstract double Operate(string operation, double a, double b);
        }
    }
    

Para crear la vista de host del complemento

  1. Agregue un nuevo proyecto denominado Calc2HVA a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.

  2. Cambie el nombre de la clase por Calculator.

  3. Convierta Calculator en una clase abstract (una clase MustInherit en Visual Basic).

  4. En el archivo de clase, utilice el código siguiente para crear la vista de host del complemento.

    Imports Microsoft.VisualBasic
    Imports System
    Namespace CalcHVAs
    
        Public MustInherit Class Calculator
    
            Public MustOverride ReadOnly Property Operations() As String
    
            Public MustOverride Function Operate(ByVal operation As String, ByVal a As Double, ByVal b As Double) As Double
        End Class
    End Namespace
    
    namespace CalcHVAs {
    
    
        public abstract class Calculator {
    
            public abstract string Operations
            {
                get;
            }
    
            public abstract double Operate(string operation, double a, double b);
        }
    }
    

Para reflejar cómo se utiliza el complemento de la versión 1 con el nuevo host, la solución debe incluir la vista de complemento creada para la versión 1 del complemento de calculadora.

Para agregar el proyecto de vista de complemento de la versión 1

  1. En el Explorador de soluciones, haga clic con el botón secundario del mouse en la solución CalculatorV2.

  2. Haga clic en Agregar y, a continuación, haga clic en Proyecto existente.

  3. Vaya a las carpetas que contienen la solución CalculatorV1 y seleccione el archivo de proyecto del proyecto Calc1AddInView.

Crear el adaptador del complemento

Este adaptador del complemento se compone de dos adaptadores de vista a contrato: uno para adaptar la vista de complemento de la versión 2 al contrato de la versión 2 y otro para adaptar la vista de complemento de la versión 1 al contrato de la versión 2.

En esta canalización, el complemento proporciona un servicio al host y los tipos fluyen del complemento al host. Dado que ningún tipo fluye del host al complemento, no es necesario incluir un adaptador de contrato a vista.

Para crear el adaptador del complemento

  1. Agregue un nuevo proyecto denominado Calc2AddInSideAdapter a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.

  2. En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto Calc2AddInSideAdapter:

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Agregue referencias de proyecto a los siguientes proyectos:

    Calc2AddInView

    Calc2Contract

  4. Seleccione la referencia de cada proyecto y en Propiedades, establezca Copia local en False para evitar que los ensamblados a los que se hace referencia se copien en la carpeta de compilación local. Los ensamblados estarán ubicados en el directorio de canalización, tal y como se describe posteriormente en el procedimiento "Implementar la canalización" de este tutorial. En Visual Basic, use la ficha Referencias de Propiedades del proyecto para establecer Copia local en False en las dos referencias del proyecto.

  5. Cambie el nombre de la clase predeterminada del proyecto CalculatorViewToContractAddInSideAdapter.

  6. En el archivo de clase, agregue una referencia de espacio de nombres a System.AddIn.Pipeline.

  7. En el archivo de clase, agregue referencias de espacio de nombres a los segmentos adyacentes: CalcAddInViews y CalculatorContracts. (En Visual Basic, estas referencias de espacio de nombres son Calc2AddInView.CalcAddInViews y Calc2Contract.CalculatorContracts, a menos que haya desactivado los espacios de nombres predeterminados en sus proyectos de Visual Basic).

  8. Utilice el código siguiente para este adaptador del complemento. El modelo de implementación es similar al del adaptador del complemento de la versión 1, aunque la interfaz del contrato es muy diferente.

    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.AddIn.Pipeline
    Imports System.AddIn.Contract
    Imports Calc2Contract.CalculatorContracts
    Imports Calc2AddInView.CalcAddInViews
    
    Namespace CalculatorContractsAddInAdapters
    
        <AddInAdapterAttribute()> _
        Public Class CalculatorViewToContractAddInAdapter
            Inherits ContractBase
            Implements ICalc2Contract
    
            Private _view As Calculator2
    
            Public Sub New(ByVal calculator As Calculator2)
                _view = calculator
            End Sub
    
            Public Function GetAvailableOperations() As String Implements ICalc2Contract.GetAvailableOperations
                Return _view.Operations
            End Function
    
            Public Function Operate(ByVal operation As String, ByVal a As Double, ByVal b As Double) As Double Implements ICalc2Contract.Operate
                Return _view.Operate(operation, a, b)
            End Function
        End Class
    End Namespace
    
    using System.AddIn.Pipeline;
    using CalcAddInViews;
    using CalculatorContracts;
    
    
    namespace CalcAddInSideAdapters {
    
    
        [AddInAdapterAttribute]
        public class CalculatorViewToContractAddInAdapter : ContractBase, ICalc2Contract {
    
            private Calculator2 _view;
    
            public CalculatorViewToContractAddInAdapter(Calculator2 calculator)
            {
                _view = calculator;
            }
    
            public string GetAvailableOperations()
            {
                return _view.Operations;
            }
    
            public double Operate(string operation, double a, double b)
            {
                return _view.Operate(operation, a, b);
            }
    
        }
    }
    

Para permitir que la versión 1 del complemento establezca comunicación con el nuevo host, la canalización del complemento de la versión 1 necesita un adaptador del complemento que convierta los datos de la antigua vista de complemento al nuevo contrato.

Para crear el adaptador de complemento de la versión 1 a la versión 2

  1. Agregue un nuevo proyecto denominado Calc2V1toV2AddInSideAdapter a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.

  2. En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto Calc2V1toV2AddInSideAdapter:

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Agregue referencias de proyecto a los siguientes proyectos:

    Calc1AddInView

    Calc2Contract

  4. Seleccione la referencia de cada proyecto y en Propiedades, establezca Copia local en False para evitar que los ensamblados a los que se hace referencia se copien en la carpeta de compilación local. En Visual Basic, use la ficha Referencias de Propiedades del proyecto para establecer Copia local en False en las dos referencias del proyecto.

  5. Cambie el nombre de la clase predeterminada del proyecto por Calc2V1ViewToV2ContractAddInSideAdapter.

  6. En el archivo de clase, agregue una referencia de espacio de nombres a System.AddIn.Pipeline.

  7. En el archivo de clase, agregue referencias de espacio de nombres a los segmentos adyacentes: CalcAddInViews y CalculatorContracts. (En Visual Basic, estas referencias de espacio de nombres son Calc1AddInView.CalcAddInViews y Calc2Contract.CalculatorContracts, a menos que haya desactivado los espacios de nombres predeterminados en sus proyectos de Visual Basic). Observe que el espacio de nombres de la vista es de la versión 1 y el contrato es de la versión 2.

  8. Aplique el atributo AddInAdapterAttribute a la clase Calc2V1ViewToV2ContractAddInSideAdapter para identificarla como el adaptador del complemento.

  9. Haga que la clase Calc2V1ViewToV2ContractAddInSideAdapter herede ContractBase, que proporciona una implementación predeterminada de la interfaz IContract e implementa la interfaz de contrato de la versión 2 para la canalización, ICalc2Contract.

  10. Agregue un constructor público que acepte ICalculator, almacénelo en la memoria caché en un campo privado y llame al constructor de clase base.

  11. Para implementar los miembros de ICalc2Contract, debe llamar a los miembros adecuados de la instancia de ICalculator que se pasa al constructor y devolver los resultados. Debido a las diferencias que existen entre las interfaces de contrato de la versión 1 y la versión 2, debe tener una instrucción switch (una instrucción Select Case en Visual Basic) para adaptar la vista (ICalculator) al contrato (ICalc2Contract).

    En el código siguiente se muestra el adaptador del complemento completado.

    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.AddIn.Pipeline
    Imports Calc1AddInView.CalcAddInViews
    Imports Calc2Contract.CalculatorContracts
    
    Namespace AddInSideV1toV2Adapter
    
    
        <AddInAdapter()> _
        Public Class Calc2V1ViewToV2ContractAddInSideAdapter
            Inherits ContractBase
            Implements ICalc2Contract
    
            Private _view As ICalculator
    
            Public Sub New(ByVal calc As ICalculator)
                MyBase.New()
                _view = calc
            End Sub
    
            Public Function GetAvailableOperations() As String Implements ICalc2Contract.GetAvailableOperations
                Return "+, -, *, /"
            End Function
    
            Public Function Operate(ByVal operation As String, ByVal a As Double, ByVal b As Double) _
             As Double Implements ICalc2Contract.Operate
                Select Case (operation)
                    Case "+"
                        Return _view.Add(a, b)
                    Case "-"
                        Return _view.Subtract(a, b)
                    Case "*"
                        Return _view.Multiply(a, b)
                    Case "/"
                        Return _view.Divide(a, b)
                    Case Else
                        Throw New InvalidOperationException(("This add-in does not support: " + operation))
                End Select
            End Function
        End Class
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.AddIn.Pipeline;
    using CalcAddInViews;
    using CalculatorContracts;
    
    
    namespace AddInSideV1toV2Adapter
    {
        [AddInAdapter]
        public class Calc2V1ViewToV2ContractAddInSideAdapter : ContractBase, ICalc2Contract
        {
            ICalculator _view;
    
            public Calc2V1ViewToV2ContractAddInSideAdapter(ICalculator calc)
            {
                _view = calc;
            }
    
            public string GetAvailableOperations()
            {
                return  "+, -, *, /" ;
            }
    
            public double Operate(string operation, double a, double b)
            {
                switch (operation)
                {
                    case "+":
                        return _view.Add(a, b);
                    case "-":
                        return _view.Subtract(a, b);
                    case "*":
                        return _view.Multiply(a, b);
                    case "/":
                        return _view.Divide(a, b);
                    default:
                        throw new InvalidOperationException("This add-in does not support: " + operation);
                }
            }
    
        }
    }
    

Crear el adaptador del host

Este adaptador del host se compone de un adaptador de contrato a vista. Un adaptador de contrato a vista es suficiente para admitir las dos versiones del complemento, porque cada adaptador del complemento convierte su vista correspondiente en el contrato de la versión 2.

En esta canalización, el complemento proporciona un servicio al host y los tipos fluyen del complemento al host. Dado que ningún tipo fluye del host al complemento, no es necesario incluir un adaptador de vista a contrato.

Si desea implementar la administración de la duración, utilice un objeto ContractHandle para asociar un token de duración al contrato. Debe mantener una referencia a este identificador para que la administración de la duración funcione. Una vez que se aplica el token, no es necesario utilizar programación adicional porque el sistema del complemento puede desechar los objetos cuando no se utilizan y hacer que estén disponibles para la recolección de elementos no utilizados. Para obtener más información, vea Administración de la duración.

Para crear el adaptador del host

  1. Agregue un nuevo proyecto denominado Calc2HostSideAdapter a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.

  2. En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto Calc2HostSideAdapter:

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Agregue referencias de proyecto a los siguientes proyectos:

    Calc2Contract

    Calc2HVA

  4. Seleccione la referencia de cada proyecto y en Propiedades, establezca Copia local en False para evitar que los ensamblados a los que se hace referencia se copien en la carpeta de compilación local. En Visual Basic, use la ficha Referencias de Propiedades del proyecto para establecer Copia local en False en las dos referencias del proyecto.

  5. Cambie el nombre de la clase predeterminada del proyecto por CalculatorContractToViewHostSideAdapter.

  6. En el archivo de clase, agregue referencias de espacio de nombres a System.AddIn.Pipeline.

  7. En el archivo de clase, agregue referencias de espacio de nombres a los segmentos adyacentes: CalcHVAs y CalculatorContracts. (En Visual Basic, estas referencias de espacio de nombres son Calc2HVA.CalcHVAs y Calc2Contract.CalculatorContracts, a menos que haya desactivado los espacios de nombres predeterminados en sus proyectos de Visual Basic).

  8. Aplique el atributo HostAdapterAttribute a la clase CalculatorContractToViewHostSideAdapter para identificarla como el adaptador del host.

  9. Haga que la clase CalculatorContractToViewHostSideAdapter herede la clase base abstracta que representa la vista de host del complemento: CalcHVAs.Calculator (Calc2HVA.CalcHVAs.Calculator en Visual Basic). Observe la diferencia respecto a la versión 1, donde la vista de host del complemento es una interfaz.

  10. Agregue un constructor público que acepte el tipo de contrato de la canalización, ICalc2Contract. El constructor debe almacenar en memoria caché la referencia del contrato. También debe crear y almacenar en caché un nuevo objeto ContractHandle del contrato para administrar la duración del complemento.

    Nota importante:

    El objeto ContractHandle resulta crítico para la administración de la duración. Si no puede mantener una referencia al objeto ContractHandle, la recolección de elementos no utilizados lo reclamará y la canalización se cerrará cuando el programa no se lo espere. Esto puede dar lugar a errores difíciles de diagnosticar, como AppDomainUnloadedException. El cierre es una etapa normal del proceso de canalización, por lo que no hay ninguna forma de que el código de administración de la duración detecte que esta condición es un error.

  11. Al invalidar los miembros de Calculator, basta con llamar a los miembros correspondientes de la instancia de ICalc2Contract que se pasó al constructor y devolver los resultados. De este modo, el contrato (ICalc2Contract) se adapta a la vista (Calculator).

    En el código siguiente se muestra el segmento del adaptador del host completado.

    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.AddIn.Pipeline
    Imports Calc2HVA.CalcHVAs
    Imports Calc2Contract.CalculatorContracts
    
    Namespace CalculatorContractsHostAdapers
        <HostAdapter()> _
        Public Class CalculatorContractToViewHostAdapter
            Inherits Calculator
    
        Private _contract As ICalc2Contract
        Private _handle As ContractHandle
    
        Public Sub New(ByVal contract As ICalc2Contract)
            _contract = contract
            _handle = New ContractHandle(contract)
        End Sub
    
        Public Overrides ReadOnly Property Operations() As String
            Get
                Return _contract.GetAvailableOperations()
            End Get
        End Property
    
        Public Overrides Function Operate(ByVal operation As String, ByVal a As Double, ByVal b As Double) As Double
            Return _contract.Operate(operation, a, b)
        End Function
    End Class
    End Namespace
    
    using System.AddIn.Pipeline;
    using CalcHVAs;
    using CalculatorContracts;
    
    namespace CalcHostSideAdapters {
    
    
    [HostAdapter]
    public class CalculatorContractToViewHostAdapter : Calculator {
    
        private CalculatorContracts.ICalc2Contract _contract;
    
        private System.AddIn.Pipeline.ContractHandle _handle;
    
        public CalculatorContractToViewHostAdapter(ICalc2Contract contract) {
            _contract = contract;
            _handle = new System.AddIn.Pipeline.ContractHandle(contract);
        }
    
    
        public override string Operations
        {
            get 
            { 
                return _contract.GetAvailableOperations(); 
            }
        }
    
        public override double Operate(string operation, double a, double b)
        {
            return _contract.Operate(operation, a, b);
        }
     }
    }
    

Crear el host

Una aplicación host interactúa con el complemento a través de la vista de host. Utiliza los métodos de detección y activación de complementos proporcionados por las clases AddInStore y AddInToken para realizar las operaciones siguientes:

  • Generar de nuevo la memoria caché de canalización y la información del complemento.

  • Buscar complementos de tipo Calculator bajo el directorio raíz de la canalización especificado.

  • Preguntar al usuario si desea especificar qué complemento va a utilizar. En este ejemplo, hay dos complementos disponibles.

  • Activar el complemento seleccionado en un nuevo dominio de aplicación con un nivel de confianza de seguridad especificado.

  • Ejecutar el método RunCalculator, que llama a los métodos del complemento proporcionados por la vista de host del complemento.

Para crear el host

  1. Agregue un nuevo proyecto denominado MathHost2 a la solución CalculatorV2. Utilice como base la plantilla Aplicación de consola.

  2. En el Explorador de soluciones, agregue una referencia del ensamblado System.AddIn.dll al proyecto MathHost2.

  3. Agregue una referencia de proyecto al proyecto Calc2HVA. Seleccione la referencia del proyecto y en Propiedades, establezca Copia local en False para evitar que el ensamblado al que se hace referencia se copie en la carpeta de compilación local. En Visual Basic, use la ficha Referencias de Propiedades del proyecto para establecer Copia local en False.

  4. Cambie el nombre del archivo de clase (módulo en Visual Basic) por MathHost2.

  5. En Visual Basic, utilice la ficha Aplicación del cuadro de diálogo Propiedades del proyecto para establecer Objeto inicial en Sub Main.

  6. En el archivo de clase o módulo, agregue una referencia de espacio de nombres a System.AddIn.Hosting.

  7. En el archivo de clase o módulo, agregue una referencia de espacio de nombres a la vista de host del complemento: CalcHVAs. (En Visual Basic, esta referencia de espacio de nombres es Calc2HVA.CalcHVAs, a menos que haya desactivado los espacios de nombres predeterminados en sus proyectos de Visual Basic).

  8. En el Explorador de soluciones, seleccione la solución y en el menú Proyecto, elija Propiedades. En el cuadro de diálogo Páginas de propiedades de la solución, establezca Proyecto de inicio único para que sea este proyecto de aplicación host.

  9. Utilice el código siguiente para crear la aplicación host:

    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    Imports System.Collections.ObjectModel
    Imports System.Text
    Imports System.AddIn.Hosting
    Imports Calc2HVA.CalcHVAs
    
    Namespace Mathhost
    
        Module MathHost2
    
            Sub Main()
                ' Assume that the current directory is the application folder, 
                ' and that it contains the pipeline folder structure. 
                Dim pipeRoot As String = Environment.CurrentDirectory & "\Pipeline"
    
                ' Rebuild the cache of pipline and add-in information.
                AddInStore.Rebuild(pipeRoot)
    
                ' Find add-ins of type Calculator under the specified pipeline root directory.
                Dim tokens As Collection(Of AddInToken) = AddInStore.FindAddIns(GetType(Calculator), pipeRoot)
    
                ' Determine which add-in to use.
                Dim calcToken As AddInToken = ChooseCalculator(tokens)
    
                ' Activate the selected AddInToken in a new  
                ' application domain with a specified security trust level.
                Dim calculator As Calculator = calcToken.Activate(Of Calculator)(AddInSecurityLevel.Internet)
    
                ' Run the calculator.
                RunCalculator(calculator)
            End Sub
    
            Private Function ChooseCalculator(ByVal tokens As Collection(Of AddInToken)) As AddInToken
                If tokens.Count = 0 Then
                    Console.WriteLine("No calculators are available")
                    Return Nothing
                End If
                Console.WriteLine("Available Calculators: ")
                ' Show the token properties for each token 
                ' in the AddInToken collection (tokens),
                ' preceded by the add-in number in [] brackets.
    
                Dim tokNumber As Integer = 1
                For Each tok As AddInToken In tokens
                    Console.WriteLine(vbTab & "[{0}]: {1} - {2}" & _
                            vbLf & vbTab & "{3}" & _
                            vbLf & vbTab & "{4}" & _
                            vbLf & vbTab & "{5} - {6}", _
                            tokNumber.ToString, tok.Name, _
                            tok.AddInFullName, tok.AssemblyName, _
                            tok.Description, tok.Version, tok.Publisher)
                    tokNumber = tokNumber + 1
                Next
                Console.WriteLine("Which calculator do you want to use?")
                Dim line As String = Console.ReadLine()
                Dim selection As Integer
                If Int32.TryParse(line, selection) Then
                    If selection <= tokens.Count Then
                        Return tokens(selection - 1)
                    End If
                End If
                Console.WriteLine("Invalid selection: {0}. Please choose again.", line)
                Return ChooseCalculator(tokens)
            End Function
    
            Private Sub RunCalculator(ByVal calc As Calculator)
    
                If calc Is Nothing Then
                    'No calculators were found, read a line and exit
                    Console.ReadLine()
                End If
                Console.WriteLine("Available operations: " & calc.Operations)
                Console.WriteLine("Request a calculation , such as: 2 + 2")
                Console.WriteLine("Type ""exit"" to exit")
                Dim line As String = Console.ReadLine()
                Do While Not line.Equals("exit")
                    ' Parser  
                    Try
                        Dim c As Parser = New Parser(line)
                        Console.WriteLine(calc.Operate(c.action, c.A, c.B))
                    Catch
                        Console.WriteLine("Invalid command: {0}. Commands must be formated: [number] [operation] [number]", line)
                        Console.WriteLine("Available operations: " & calc.Operations)
                    End Try
    
                    line = Console.ReadLine()
                Loop
            End Sub
        End Module
    
    
        Friend Class Parser
    
            Public partA As Double
    
            Public partB As Double
    
            Public action As String
    
            Friend Sub New(ByVal line As String)
                MyBase.New()
                Dim parts() As String = line.Split(" ")
                partA = Double.Parse(parts(0))
                action = parts(1)
                partB = Double.Parse(parts(2))
            End Sub
    
            Public ReadOnly Property A() As Double
                Get
                    Return partA
                End Get
            End Property
    
            Public ReadOnly Property B() As Double
                Get
                    Return partB
                End Get
            End Property
    
            Public ReadOnly Property CalcAction() As String
                Get
                    Return action
                End Get
            End Property
        End Class
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Text;
    using System.AddIn.Hosting;
    using CalcHVAs;
    
    namespace MathHost
    {
        class Program
        {
            static void Main()
            {
                // Assume that the current directory is the application folder, 
                // and that it contains the pipeline folder structure. 
                String addInRoot = Environment.CurrentDirectory + "\\Pipeline";
    
                //Check to see if new add-ins have been installed.
                AddInStore.Rebuild(addInRoot);
    
                //Search for Calculator add-ins.
                Collection<AddInToken> tokens = AddInStore.FindAddIns(typeof(Calculator), addInRoot);
    
                //Ask the user which add-in they would like to use.
                AddInToken calcToken = ChooseCalculator(tokens);
    
                //Activate the selected AddInToken in a new
                //application domain with the Internet trust level.
                Calculator calculator = calcToken.Activate<Calculator>(AddInSecurityLevel.Internet);
    
                //Run the add-in.
                RunCalculator(calculator);
            }
    
            private static AddInToken ChooseCalculator(Collection<AddInToken> tokens)
            {
                if (tokens.Count == 0)
                {
                    Console.WriteLine("No calculators are available");
                    return null;
                }
                Console.WriteLine("Available Calculators: ");
                // Show the token properties for each token 
                // in the AddInToken collection (tokens),
                // preceded by the add-in number in [] brackets.
                int tokNumber = 1;
                foreach (AddInToken tok in tokens)
                {
                    Console.WriteLine(String.Format("\t[{0}]: {1} - {2}\n\t{3}\n\t\t {4}\n\t\t {5} - {6}",
                        tokNumber.ToString(), 
                        tok.Name,
                        tok.AddInFullName,
                        tok.AssemblyName,
                        tok.Description,
                        tok.Version,
                        tok.Publisher));
                    tokNumber++;
                }
                Console.WriteLine("Which calculator do you want to use?");
                String line = Console.ReadLine();
                int selection;
                if (Int32.TryParse(line, out selection))
                {
                    if (selection <= tokens.Count)
                    {
                        return tokens[selection - 1];
                    }
                }
                Console.WriteLine("Invalid selection: {0}. Please choose again.", line);
                return ChooseCalculator(tokens);
            }
    
            private static void RunCalculator(Calculator calc)
            {
    
                if (calc == null)
                {
                    //No calculators were found, read a line and exit.
                    Console.ReadLine();
                }
                Console.WriteLine("Available operations: " + calc.Operations);
                Console.WriteLine("Type \"exit\" to exit");
                String line = Console.ReadLine();
                while (!line.Equals("exit"))
                {
                    // The Parser class parses the user's input.
                    try
                    {
                        Parser c = new Parser(line);
                        Console.WriteLine(calc.Operate(c.Action, c.A, c.B));
                    }
                    catch
                    {
                        Console.WriteLine("Invalid command: {0}. Commands must be formated: [number] [operation] [number]", line);
                        Console.WriteLine("Available operations: " + calc.Operations);
                    }
    
                    line = Console.ReadLine();
                }
            }
        }
    
    
        internal class Parser
        {
            internal Parser(String line)
            {
                String[] parts = line.Trim().Split(' ');
                a = Double.Parse(parts[0]);
                action = parts[1];
                b = Double.Parse(parts[2]);
            }
    
            double a;
    
            public double A
            {
                get { return a; }
            }
            double b;
    
            public double B
            {
                get { return b; }
            }
            String action;
    
            public String Action
            {
                get { return action; }
            }
        }
    }
    
    Nota:

    En este código se presupone que la estructura de carpetas de la canalización se encuentra en la carpeta de la aplicación. Si, por el contrario, se encuentra en otra ubicación, cambie la línea de código en la que se establece la variable addInRoot para que la variable contenga la ruta de acceso a la estructura de directorios de la canalización.

Crear el complemento

Un complemento implementa los métodos especificados por la vista de complemento. En este complemento, el método Operations devuelve una cadena que muestra las operaciones matemáticas que el complemento admite. El método Operate proporciona el código que va a calcular el resultado en función de la operación y los dos números que se seleccionen en el host.

Para crear el complemento

  1. Agregue un nuevo proyecto denominado AddInCalcV2 a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.

  2. En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto AddInCalcV2:

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Agregue una referencia de proyecto al proyecto Calc2AddInView. Seleccione la referencia del proyecto y en Propiedades, establezca Copia local en False para evitar que el ensamblado al que se hace referencia se copie en la carpeta de compilación local. En Visual Basic, use la ficha Referencias de Propiedades del proyecto para establecer Copia local en False.

  4. Cambie el nombre del archivo de clase por SampleV2AddIn.

  5. En el archivo de clase, agregue referencias de espacio de nombres a System.AddIn y System.AddIn.Pipeline. System.AddIn.Pipeline sólo es necesario porque el código incluye un ejemplo del atributo QualificationDataAttribute.

  6. En el archivo de clase, agregue una referencia de espacio de nombres para el segmento de la vista de complemento de la versión 2: CalcAddInViews (Calc2AddInView.CalcAddInViews en Visual Basic).

  7. Aplique el atributo AddInAttribute a la clase SampleV2AddIn para identificar la clase como un complemento.

  8. Aplique el atributo QualificationDataAttribute a la clase SampleV2AddIn y especifique la información que el host puede recuperar de AddInToken. En este caso, la información sugiere que el complemento debe cargarse en su propio dominio de aplicación. Vea Cómo: Usar datos de calificación.

  9. Haga que la clase SampleV2AddIn herede la clase base abstracta que representa la vista de complemento: Calculator2.

  10. Invalide los miembros de Calculator2 y devuelva los resultados de los cálculos adecuados.

    En el código siguiente se muestra el complemento completado.

    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.AddIn
    Imports System.AddIn.Pipeline
    Imports Calc2AddInView.CalcAddInViews
    
    Namespace CalculatorAddIns
    ' This pipeline segment has
    ' two attributes:
    ' 1 - An AddInAttribute to identify
    '     this segment as an add-in.
    '
    ' 2 - A QualificationDataAttribute to
    '     indicate that the add-in should
    '     be loaded into a new application domain.
    
    <AddIn("Calculator Add-in", Version:="2.0.0.0")> _
    <QualificationData("Isolation", "NewAppDomain")> _
        Public Class SampleV2AddIn
        Inherits Calculator2
    Public Overrides ReadOnly Property Operations() As String
        Get
            Return "+, -, *, /, **"
        End Get
    End Property
    
    Public Overrides Function Operate(ByVal operation As String, _
            ByVal a As Double, ByVal b As Double) As Double
        Select Case operation
            Case "+"
                Return a + b
            Case "-"
                Return a - b
            Case "*"
                Return a * b
            Case "/"
                Return a / b
            Case "**"
                Return Math.Pow(a, b)
            Case Else
                Throw New InvalidOperationException("This add-in does not support: " & operation)
        End Select
    End Function
    
    End Class
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.AddIn;
    using System.AddIn.Pipeline;
    using CalcAddInViews;
    namespace CalcAddIns
    {
    // This pipeline segment has
    // two attributes:
    // 1 - An AddInAttribute to identify
    //     this segment as an add-in.
    //
    // 2 - A QualificationDataAttribute to
    //     indicate that the add-in should
    //     be loaded into a new application domain.
    
        [AddIn("Calculator Add-in",Version="2.0.0.0")]
        [QualificationData("Isolation", "NewAppDomain")]
        public class SampleV2AddIn : Calculator2
        {
            public override string Operations
            {
                get
                {
                    return "+, -, *, /, **";
                }
            }
    
            public override double Operate(string operation, double a, double b)
            {
                switch (operation)
                {
                    case "+":
                        return a + b;
                    case "-":
                        return a - b;
                    case "*":
                        return a * b;
                    case "/":
                        return a / b;
                    case "**":
                        return Math.Pow(a, b);
                    default:
                        throw new InvalidOperationException("This add-in does not support: " + operation);
                }
            }
    
        }
    }
    

Implementar la canalización

Ya está listo para generar e implementar los segmentos de los complementos en la estructura de directorios de canalización requerida.

Para implementar los segmentos en la canalización

  1. En cada proyecto de la solución, utilice la ficha Generar de Propiedades del proyecto (la ficha Compilar en Visual Basic) para establecer el valor de Ruta de acceso de los resultados (Ruta de acceso de los resultados de la compilación en Visual Basic). Si, por ejemplo, denominara a su carpeta de aplicación MyApp, sus proyectos se generarían en las carpetas siguientes:

    Proyecto

    Ruta de acceso

    AddInCalcV2

    MyApp\Pipeline\AddIns\CalcV2

    Calc2AddInSideAdapter

    MyApp\Pipeline\AddInSideAdapters

    Calc2V1toV2AddInSideAdapter

    MyApp\Pipeline\AddInSideAdapters

    Calc1AddInView

    MyApp\Pipeline\AddInViews

    Calc2AddInView

    MyApp\Pipeline\AddInViews

    Calc2Contract

    MyApp\Pipeline\Contracts

    MathHost2

    MyApp

    Calc2HostSideAdapter

    MyApp\Pipeline\HostSideAdapters

    Calc2HVA

    MyApp

    Nota:

    Si sitúa la estructura de carpetas de la canalización en una ubicación distinta a la carpeta de la aplicación, deberá modificar las rutas de acceso que aparecen en la tabla como corresponda.

  2. Genere la solución de Visual Studio.

  3. Compruebe los directorios de la canalización y la aplicación para asegurarse de que los ensamblados se copiaron en los directorios correctos y de que no se copió ninguna copia adicional de los ensamblados en carpetas equivocadas.

    Nota:

    Si no cambió Copia local a False en la referencia Calc2AddInView del proyecto AddInCalcV2, los problemas contextuales del programa de carga impedirán que se pueda encontrar el complemento.

    Para obtener información acerca de cómo se realiza la implementación en la canalización, vea Requisitos del desarrollo de canalizaciones.

Ejecutar la aplicación host

Ya está listo para ejecutar el host e interactuar con los complementos.

Para ejecutar la aplicación host

  1. Asegúrese de que se han implementado las dos versiones del complemento.

  2. En el símbolo del sistema, vaya al directorio de la aplicación y ejecute la aplicación host. En este ejemplo, la aplicación host es MathHost2.exe.

  3. El host busca todos los complementos disponibles de su tipo y le solicita que seleccione un complemento. Escriba 1 o 2.

  4. Escriba una ecuación para la calculadora, como 2 + 2.

  5. Escriba exit y presione la tecla Entrar para cerrar la aplicación.

  6. Repita los pasos del 2 al 5 para ejecutar el otro complemento.

Vea también

Tareas

Tutorial: Crear una aplicación extensible

Tutorial: Pasar colecciones entre hosts y complementos

Conceptos

Requisitos del desarrollo de canalizaciones

Contratos, vistas y adaptadores

Desarrollo de canalizaciones

Historial de cambios

Fecha

Historial

Motivo

Julio de 2008

Errores corregidos en el texto. Se agregó una nota acerca de la forma de mantener una referencia al contrato.

Comentarios de los clientes.