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
En Visual Studio, cree un nuevo proyecto denominado Calc2Contract. Utilice como base la plantilla Biblioteca de clases.
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
En la solución de Visual Studio denominada CalculatorV2, abra el proyecto Calc2Contract.
En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto Calc2Contract:
System.AddIn.Contract.dll
System.AddIn.dll
En el Explorador de soluciones, excluya la clase predeterminada que se agrega a los nuevos proyectos de Biblioteca de clases.
Agregue un nuevo elemento al proyecto utilizando la plantilla Interfaz. En el cuadro de diálogo Agregar nuevo elemento, denomine la interfaz ICalc2Contract.
En el archivo de interfaz, agregue referencias de espacio de nombres a System.AddIn.Contract y System.AddIn.Pipeline.
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
Agregue un nuevo proyecto denominado Calc2AddInView a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.
En el Explorador de soluciones, agregue una referencia de System.AddIn.dll al proyecto Calc2AddInView.
Cambie el nombre de la clase por Calculator2.
En el archivo de clase, agregue una referencia de espacio de nombres a System.AddIn.Pipeline.
Convierta Calculator2 en una clase abstract (una clase MustInherit en Visual Basic).
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
Agregue un nuevo proyecto denominado Calc2HVA a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.
Cambie el nombre de la clase por Calculator.
Convierta Calculator en una clase abstract (una clase MustInherit en Visual Basic).
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
En el Explorador de soluciones, haga clic con el botón secundario del mouse en la solución CalculatorV2.
Haga clic en Agregar y, a continuación, haga clic en Proyecto existente.
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
Agregue un nuevo proyecto denominado Calc2AddInSideAdapter a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.
En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto Calc2AddInSideAdapter:
System.AddIn.dll
System.AddIn.Contract.dll
Agregue referencias de proyecto a los siguientes proyectos:
Calc2AddInView
Calc2Contract
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.
Cambie el nombre de la clase predeterminada del proyecto CalculatorViewToContractAddInSideAdapter.
En el archivo de clase, agregue una referencia de espacio de nombres a System.AddIn.Pipeline.
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).
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
Agregue un nuevo proyecto denominado Calc2V1toV2AddInSideAdapter a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.
En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto Calc2V1toV2AddInSideAdapter:
System.AddIn.dll
System.AddIn.Contract.dll
Agregue referencias de proyecto a los siguientes proyectos:
Calc1AddInView
Calc2Contract
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.
Cambie el nombre de la clase predeterminada del proyecto por Calc2V1ViewToV2ContractAddInSideAdapter.
En el archivo de clase, agregue una referencia de espacio de nombres a System.AddIn.Pipeline.
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.
Aplique el atributo AddInAdapterAttribute a la clase Calc2V1ViewToV2ContractAddInSideAdapter para identificarla como el adaptador del complemento.
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.
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.
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
Agregue un nuevo proyecto denominado Calc2HostSideAdapter a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.
En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto Calc2HostSideAdapter:
System.AddIn.dll
System.AddIn.Contract.dll
Agregue referencias de proyecto a los siguientes proyectos:
Calc2Contract
Calc2HVA
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.
Cambie el nombre de la clase predeterminada del proyecto por CalculatorContractToViewHostSideAdapter.
En el archivo de clase, agregue referencias de espacio de nombres a System.AddIn.Pipeline.
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).
Aplique el atributo HostAdapterAttribute a la clase CalculatorContractToViewHostSideAdapter para identificarla como el adaptador del host.
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.
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.
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
Agregue un nuevo proyecto denominado MathHost2 a la solución CalculatorV2. Utilice como base la plantilla Aplicación de consola.
En el Explorador de soluciones, agregue una referencia del ensamblado System.AddIn.dll al proyecto MathHost2.
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.
Cambie el nombre del archivo de clase (módulo en Visual Basic) por MathHost2.
En Visual Basic, utilice la ficha Aplicación del cuadro de diálogo Propiedades del proyecto para establecer Objeto inicial en Sub Main.
En el archivo de clase o módulo, agregue una referencia de espacio de nombres a System.AddIn.Hosting.
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).
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.
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
Agregue un nuevo proyecto denominado AddInCalcV2 a la solución CalculatorV2. Utilice como base la plantilla Biblioteca de clases.
En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto AddInCalcV2:
System.AddIn.dll
System.AddIn.Contract.dll
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.
Cambie el nombre del archivo de clase por SampleV2AddIn.
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.
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).
Aplique el atributo AddInAttribute a la clase SampleV2AddIn para identificar la clase como un complemento.
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.
Haga que la clase SampleV2AddIn herede la clase base abstracta que representa la vista de complemento: Calculator2.
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
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.
Genere la solución de Visual Studio.
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
Asegúrese de que se han implementado las dos versiones del complemento.
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.
El host busca todos los complementos disponibles de su tipo y le solicita que seleccione un complemento. Escriba 1 o 2.
Escriba una ecuación para la calculadora, como 2 + 2.
Escriba exit y presione la tecla Entrar para cerrar la aplicación.
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
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. |