Tutorial: Crear una aplicación extensible
En este tutorial se describe cómo se crea una canalización para un complemento que realiza las funciones de una calculadora sencilla. No muestra un escenario real; más bien, muestra la funcionalidad básica de una canalización y cómo un complemento puede proporcionar servicios a un host.
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 de conversión.
Crear el adaptador del host.
Crear el host.
Crear el complemento.
Implementar la canalización.
Ejecutar la aplicación host.
Esta canalización sólo pasa tipos serializables (Double y String) entre el host y el complemento. Para obtener un ejemplo en el que se muestra cómo se pasan colecciones de tipos de datos complejos, vea Tutorial: Pasar colecciones entre hosts y complementos.
El contrato de esta canalización define un modelo de objetos de cuatro operaciones aritméticas: sumar, restar, multiplicar y dividir. El host proporciona al complemento una ecuación que hay que calcular, por ejemplo 2 + 2, y el complemento devuelve el resultado al host.
La versión 2 del complemento de calculadora proporciona otras posibilidades de cálculo y muestra el control de versiones. Esta versión se describe en Tutorial: Habilitar la compatibilidad con versiones anteriores al cambiar el host.
Nota |
---|
Puede encontrar más código de ejemplo y vistas previas de herramientas con la tecnología de clientes para compilar canalizaciones de complementos en el sitio Managed Extensibility and Add-In Framework de CodePlex. |
Requisitos previos
Necesita lo siguiente para poder llevar a cabo este tutorial:
- Visual Studio.
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 Calc1Contract. Utilice como base la plantilla Biblioteca de clases.
Llame a la solución CalculatorV1.
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 obtener más información sobre la estructura de canalización, vea Requisitos del desarrollo de canalizaciones.
Para crear la estructura de directorios de canalización
Cree en una carpeta de aplicación en cualquier ubicación del equipo.
En esa carpeta, cree la estructura siguiente:
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; aquí sólo lo hacemos por comodidad. En el paso correspondiente, el tutorial explica cómo debe cambiarse el código si la estructura de carpetas de la canalización se encuentra en una ubicación diferente. Vea los comentarios sobre los requisitos de los directorios de la canalización en Requisitos del desarrollo de canalizaciones.
Nota La carpeta CalcV2 no se utiliza en este tutorial; es un marcador de posición de Tutorial: Habilitar la compatibilidad con versiones anteriores al cambiar el host.
Crear el contrato y las vistas
El segmento del contrato de esta canalización define la interfaz ICalc1Contract, que, a su vez, define cuatro métodos: add, subtract, multiply y divide.
Para crear el contrato
En la solución de Visual Studio denominada CalculatorV1, abra el proyecto Calc1Contract.
En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto Calc1Contract:
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.
En el Explorador de soluciones, agregue un nuevo elemento al proyecto utilizando la plantilla Interfaz. En el cuadro de diálogo Agregar nuevo elemento, denomine la interfaz ICalc1Contract.
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 este segmento del contrato. Tenga en cuenta que esta interfaz debe tener el atributo AddInContractAttribute.
Imports System.AddIn.Contract Imports System.AddIn.Pipeline Namespace CalculatorContracts ' The AddInContractAttribute identifes this pipeline segment as a ' contract. <AddInContract()> _ Public Interface ICalc1Contract Inherits IContract Function Add(ByVal a As Double, ByVal b As Double) As Double Function Subtract(ByVal a As Double, ByVal b As Double) As Double Function Multiply(ByVal a As Double, ByVal b As Double) As Double Function Divide(ByVal a As Double, ByVal b As Double) As Double End Interface End Namespace
using System.AddIn.Contract; using System.AddIn.Pipeline; namespace CalculatorContracts { // The AddInContractAttribute identifes this pipeline segment as a // contract. [AddInContract] public interface ICalc1Contract : IContract { double Add(double a, double b); double Subtract(double a, double b); double Multiply(double a, double b); double Divide(double a, double b); } }
De manera opcional, compile la solución de Visual Studio. La solución no se puede ejecutarse hasta el procedimiento final, pero si la compila después de cada procedimiento, se asegura de que cada proyecto es correcto.
Dado que la vista de complemento y la vista de host del complemento normalmente tienen el mismo código, en concreto la primera versión del complemento, resulta sencillo crear las vistas 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
Agregue un nuevo proyecto denominado Calc1AddInView a la solución CalculatorV1. Utilice como base la plantilla Biblioteca de clases.
En el Explorador de soluciones, agregue una referencia de System.AddIn.dll al proyecto Calc1AddInView.
En el Explorador de soluciones, excluya la clase predeterminada que se agrega a los nuevos proyectos de Biblioteca de clases y agregue un nuevo elemento al proyecto, utilizando la plantilla Interfaz. En el cuadro de diálogo Agregar nuevo elemento, denomine la interfaz ICalculator.
En el archivo de interfaz, agregue una referencia de espacio de nombres a System.AddIn.Pipeline.
Utilice el código siguiente para completar esta vista de complemento. Tenga en cuenta que esta interfaz debe tener el atributo AddInBaseAttribute.
Imports System.AddIn.Pipeline Namespace CalcAddInViews ' The AddInBaseAttribute identifes this interface as the basis for the ' add-in view pipeline segment. <AddInBaseAttribute()> _ Public Interface ICalculator Function Add(ByVal a As Double, ByVal b As Double) As Double Function Subtract(ByVal a As Double, ByVal b As Double) As Double Function Multiply(ByVal a As Double, ByVal b As Double) As Double Function Divide(ByVal a As Double, ByVal b As Double) As Double End Interface End Namespace
using System.AddIn.Pipeline; namespace CalcAddInViews { // The AddInBaseAttribute identifes this interface as the basis for // the add-in view pipeline segment. [AddInBase()] public interface ICalculator { double Add(double a, double b); double Subtract(double a, double b); double Multiply(double a, double b); double Divide(double a, double b); } }
De manera opcional, compile la solución de Visual Studio.
Para crear la vista de host del complemento
Agregue un nuevo proyecto denominado Calc1HVA a la solución CalculatorV1. Utilice como base la plantilla Biblioteca de clases.
En el Explorador de soluciones, excluya la clase predeterminada que se agrega a los nuevos proyectos de Biblioteca de clases y agregue un nuevo elemento al proyecto, utilizando la plantilla Interfaz. En el cuadro de diálogo Agregar nuevo elemento, denomine la interfaz ICalculator.
En el archivo de interfaz, utilice el código siguiente para completar la vista de host del complemento.
Namespace CalcHVAs Public Interface ICalculator Function Add(ByVal a As Double, ByVal b As Double) As Double Function Subtract(ByVal a As Double, ByVal b As Double) As Double Function Multiply(ByVal a As Double, ByVal b As Double) As Double Function Divide(ByVal a As Double, ByVal b As Double) As Double End Interface End Namespace
namespace CalcHVAs { public interface ICalculator { double Add(double a, double b); double Subtract(double a, double b); double Multiply(double a, double b); double Divide(double a, double b); } }
De manera opcional, compile la solución de Visual Studio.
Crear el adaptador de conversión
Este adaptador de conversión se compone de un adaptador de vista a contrato. Este segmento de la canalización convierte los tipos de la vista de complemento al contrato.
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 en el complemento de esta canalización.
Para crear el adaptador de conversión
Agregue un nuevo proyecto denominado Calc1AddInSideAdapter a la solución CalculatorV1. Utilice como base la plantilla Biblioteca de clases.
En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto Calc1AddInSideAdapter:
System.AddIn.dll
System.AddIn.Contract.dll
Agregue referencias a los proyectos en los segmentos del conductor adyacentes:
Calc1AddInView
Calc1Contract
Seleccione la referencia de cada proyecto y en Propiedades establezca Copia local en False. 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 referencias de espacio de nombres a System.AddIn.Pipeline.
En el archivo de clases, 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 Calc1Contract.CalculatorContracts, a menos que haya desactivado los espacios de nombres predeterminados en sus proyectos de Visual Basic).
Aplique el atributo AddInAdapterAttribute a la clase CalculatorViewToContractAddInSideAdapter para identificarla como el adaptador de conversión.
Haga que la clase CalculatorViewToContractAddInSideAdapter herede ContractBase, que proporciona una implementación predeterminada de la interfaz IContract e implementa la interfaz del contrato de la canalización, ICalc1Contract.
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 ICalc1Contract, sólo necesita llamar a los miembros correspondientes de la instancia de ICalculator que se pasa al constructor y devolver los resultados. De este modo, la vista (ICalculator) se adapta al contrato (ICalc1Contract).
En el código siguiente se muestra el adaptador de conversión completado.
Imports System.AddIn.Pipeline Imports Calc1AddInView.CalcAddInViews Imports Calc1Contract.CalculatorContracts Namespace CalcAddInSideAdapters ' The AddInAdapterAttribute identifes this class as the add-in-side ' adapter pipeline segment. <AddInAdapter()> _ Public Class CalculatorViewToContractAddInSideAdapter Inherits ContractBase Implements ICalc1Contract Private _view As ICalculator Public Sub New(ByVal view As ICalculator) MyBase.New() _view = view End Sub Public Function Add(ByVal a As Double, ByVal b As Double) As Double Implements ICalc1Contract.Add Return _view.Add(a, b) End Function Public Function Subtract(ByVal a As Double, ByVal b As Double) As Double Implements ICalc1Contract.Subtract Return _view.Subtract(a, b) End Function Public Function Multiply(ByVal a As Double, ByVal b As Double) As Double Implements ICalc1Contract.Multiply Return _view.Multiply(a, b) End Function Public Function Divide(ByVal a As Double, ByVal b As Double) As Double Implements ICalc1Contract.Divide Return _view.Divide(a, b) End Function End Class End Namespace
using System.AddIn.Pipeline; using CalcAddInViews; using CalculatorContracts; namespace CalcAddInSideAdapters { // The AddInAdapterAttribute identifes this class as the add-in-side adapter // pipeline segment. [AddInAdapter()] public class CalculatorViewToContractAddInSideAdapter : ContractBase, ICalc1Contract { private ICalculator _view; public CalculatorViewToContractAddInSideAdapter(ICalculator view) { _view = view; } public virtual double Add(double a, double b) { return _view.Add(a, b); } public virtual double Subtract(double a, double b) { return _view.Subtract(a, b); } public virtual double Multiply(double a, double b) { return _view.Multiply(a, b); } public virtual double Divide(double a, double b) { return _view.Divide(a, b); } } }
De manera opcional, compile la solución de Visual Studio.
Crear el adaptador del host
Este adaptador del host se compone de un adaptador de contrato a vista. Este segmento adapta el contrato a la vista de host del complemento.
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 Calc1HostSideAdapter a la solución CalculatorV1. Utilice como base la plantilla Biblioteca de clases.
En el Explorador de soluciones, agregue referencias de los siguientes ensamblados al proyecto Calc1HostSideAdapter:
System.AddIn.dll
System.AddIn.Contract.dll
Agregue referencias a los proyectos en los segmentos adyacentes:
Calc1Contract
Calc1HVA
Seleccione la referencia de cada proyecto y en Propiedades establezca Copia local en False. 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 clases, agregue referencias de espacio de nombres a los segmentos adyacentes: CalcHVAs y CalculatorContracts. (En Visual Basic, estas referencias de espacio de nombres son Calc1HVA.CalcHVAs y Calc1Contract.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 segmento del adaptador del host.
Haga que la clase CalculatorContractToViewHostSideAdapter herede la interfaz que representa la vista de host del complemento: Calc1HVAs.ICalculator (Calc1HVA.CalcHVAs.ICalculator en Visual Basic).
Agregue un constructor público que acepte el tipo de contrato de la canalización, ICalc1Contract. 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.
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.
Para implementar los miembros de ICalculator, sólo necesita llamar a los miembros correspondientes de la instancia de ICalc1Contract que se pasa al constructor y devolver los resultados. De este modo, el contrato (ICalc1Contract) se adapta a la vista (ICalculator).
En el código siguiente se muestra el adaptador del host completado.
Imports System.AddIn.Pipeline Imports Calc1Contract.CalculatorContracts Imports Calc1HVA.CalcHVAs Namespace CalcHostSideAdapters ' The HostAdapterAttribute identifes this class as the host-side adapter ' pipeline segment. <HostAdapterAttribute()> _ Public Class CalculatorContractToViewHostSideAdapter Implements ICalculator Private _contract As ICalc1Contract Private _handle As System.AddIn.Pipeline.ContractHandle Public Sub New(ByVal contract As ICalc1Contract) MyBase.New() _contract = contract _handle = New ContractHandle(contract) End Sub Public Function Add(ByVal a As Double, ByVal b As Double) As Double _ Implements ICalculator.Add Return _contract.Add(a, b) End Function Public Function Subtract(ByVal a As Double, ByVal b As Double) As Double _ Implements ICalculator.Subtract Return _contract.Subtract(a, b) End Function Public Function Multiply(ByVal a As Double, ByVal b As Double) As Double _ Implements ICalculator.Multiply Return _contract.Multiply(a, b) End Function Public Function Divide(ByVal a As Double, ByVal b As Double) As Double _ Implements ICalculator.Divide Return _contract.Divide(a, b) End Function End Class End Namespace
using System.AddIn.Pipeline; using CalcHVAs; using CalculatorContracts; namespace CalcHostSideAdapters { // The HostAdapterAttribute identifes this class as the host-side adapter // pipeline segment. [HostAdapterAttribute()] public class CalculatorContractToViewHostSideAdapter : ICalculator { private ICalc1Contract _contract; private System.AddIn.Pipeline.ContractHandle _handle; public CalculatorContractToViewHostSideAdapter(ICalc1Contract contract) { _contract = contract; _handle = new ContractHandle(contract); } public double Add(double a, double b) { return _contract.Add(a, b); } public double Subtract(double a, double b) { return _contract.Subtract(a, b); } public double Multiply(double a, double b) { return _contract.Multiply(a, b); } public double Divide(double a, double b) { return _contract.Divide(a, b); } } }
De manera opcional, compile la solución de Visual Studio.
Crear el host
Una aplicación host interactúa con el complemento a través de la vista de host del complemento. Utiliza los métodos de detección y activación de complementos proporcionados por las clases AddInStore y AddInToken para realizar las operaciones siguientes:
Actualizar de nuevo la memoria caché de canalización y la información del complemento.
Buscar complementos del tipo de la vista de host, ICalculator, bajo el directorio raíz de la canalización especificado.
Preguntar al usuario si desea especificar qué complemento va a utilizar.
Activar el complemento seleccionado en un nuevo dominio de aplicación con un nivel de confianza de seguridad especificado.
Ejecutar el método RunCalculator personalizado, que llama a los métodos del complemento en función de las especificaciones de la vista de host del complemento.
Para crear el host
Agregue un nuevo proyecto denominado Calc1Host a la solución CalculatorV1. Utilice como base la plantilla Aplicación de consola.
En el Explorador de soluciones, agregue una referencia del ensamblado System.AddIn.dll al proyecto Calc1Host.
Agregue una referencia de proyecto al proyecto Calc1HVA. Seleccione la referencia del proyecto y en Propiedades establezca Copia local en False. 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 MathHost1.
En Visual Basic, utilice la ficha Aplicación del cuadro de diálogo Propiedades del proyecto para establecer Objeto de inicio 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 Calc1HVA.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.
En el archivo de clase o módulo, utilice el método AddInStore.Update para actualizar la memoria caché. Utilice el método AddInStore.FindAddIn para obtener una colección de tokens y utilice el método AddInToken.Activate para activar un complemento.
En el código siguiente se muestra la aplicación host completada.
Imports System.Collections.Generic Imports System.Collections.ObjectModel Imports System.AddIn.Hosting Imports Calc1HVA.CalcHVAs Namespace MathHost Module MathHost1 Sub Main() ' Assume that the current directory is the application folder, ' and that it contains the pipeline folder structure. Dim addInRoot As String = Environment.CurrentDirectory & "\Pipeline" ' Update the cache files of the pipeline segments and add-ins. Dim warnings() As String = AddInStore.Update(addInRoot) For Each warning As String In warnings Console.WriteLine(warning) Next ' Search for add-ins of type ICalculator (the host view of the add-in). Dim tokens As System.Collections.ObjectModel.Collection(Of AddInToken) = _ AddInStore.FindAddIns(GetType(ICalculator), addinRoot) ' Ask the user which add-in they would like to use. Dim calcToken As AddInToken = ChooseCalculator(tokens) ' Activate the selected AddInToken in a new application domain ' with the Internet trust level. Dim calc As ICalculator = _ calcToken.Activate(Of ICalculator)(AddInSecurityLevel.Internet) ' Run the add-in. RunCalculator(calc) 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 ICalculator) If IsNothing(calc) Then 'No calculators were found, read a line and exit. Console.ReadLine() End If Console.WriteLine("Available operations: +, -, *, /") Console.WriteLine("Request a calculation , such as: 2 + 2") Console.WriteLine("Type 'exit' to exit") Dim line As String = Console.ReadLine While Not line.Equals("exit") ' The Parser class parses the user's input. Try Dim c As Parser = New Parser(line) Select Case (c.action) Case "+" Console.WriteLine(calc.Add(c.a, c.b)) Case "-" Console.WriteLine(calc.Subtract(c.a, c.b)) Case "*" Console.WriteLine(calc.Multiply(c.a, c.b)) Case "/" Console.WriteLine(calc.Divide(c.a, c.b)) Case Else Console.WriteLine("{0} is an invalid command. Valid commands are +,-,*,/", c.action) End Select Catch Ex As System.Exception Console.WriteLine("Invalid command: {0}. Commands must be formated: [number] [operation] [number]", line) End Try line = Console.ReadLine End While End Sub End Module 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.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"; // Update the cache files of the pipeline segments and add-ins. string[] warnings = AddInStore.Update(addInRoot); foreach (string warning in warnings) { Console.WriteLine(warning); } // Search for add-ins of type ICalculator (the host view of the add-in). Collection<AddInToken> tokens = AddInStore.FindAddIns(typeof(ICalculator), 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. ICalculator calc = calcToken.Activate<ICalculator>(AddInSecurityLevel.Internet); // Run the add-in. RunCalculator(calc); } 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(ICalculator calc) { if (calc == null) { //No calculators were found; read a line and exit. Console.ReadLine(); } Console.WriteLine("Available operations: +, -, *, /"); Console.WriteLine("Request a calculation , such as: 2 + 2"); 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); switch (c.Action) { case "+": Console.WriteLine(calc.Add(c.A, c.B)); break; case "-": Console.WriteLine(calc.Subtract(c.A, c.B)); break; case "*": Console.WriteLine(calc.Multiply(c.A, c.B)); break; case "/": Console.WriteLine(calc.Divide(c.A, c.B)); break; default: Console.WriteLine("{0} is an invalid command. Valid commands are +,-,*,/", c.Action); break; } } catch { Console.WriteLine("Invalid command: {0}. Commands must be formated: [number] [operation] [number]", line); } line = Console.ReadLine(); } } } internal class Parser { double a; double b; string action; internal Parser(string line) { string[] parts = line.Split(' '); a = double.Parse(parts[0]); action = parts[1]; b = double.Parse(parts[2]); } public double A { get { return a; } } public double B { get { return b; } } 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.
El código utiliza un método ChooseCalculator para hacer una lista de los tokens y solicitar al usuario que elija un complemento. El método RunCalculator solicita al usuario que escriba expresiones matemáticas simples, analiza las expresiones utilizando la clase Parser y muestra los resultados devueltos por el complemento.
De manera opcional, compile la solución de Visual Studio.
Crear el complemento
Un complemento implementa los métodos especificados por la vista de complemento. Este complemento implementa las operaciones Add, Subtract, Multiply y Divide y devuelve los resultados al host.
Para crear el complemento
Agregue un nuevo proyecto denominado AddInCalcV1 a la solución CalculatorV1. Utilice como base la plantilla Biblioteca de clases.
En el Explorador de soluciones, agregue una referencia del ensamblado System.AddIn.dll al proyecto.
Agregue una referencia al proyecto Calc1AddInView. Seleccione la referencia del proyecto y en Propiedades, establezca Copia local en False. En Visual Basic, use la ficha Referencias de Propiedades del proyecto para establecer Copia local en False en la referencia del proyecto.
Cambie el nombre de la clase a AddInCalcV1.
En el archivo de clase, agregue una referencia de espacio de nombres a System.AddIn y el segmento de la vista de complemento: CalcAddInViews (Calc1AddInView.CalcAddInViews en Visual Basic).
Aplique el atributo AddInAttribute a la clase AddInCalcV1 para identificar la clase como un complemento.
Haga que la clase AddInCalcV1 implemente la interfaz que representa la vista de complemento: CalcAddInViews.ICalculator (Calc1AddInView.CalcAddInViews.ICalculator en Visual Basic).
Para implementar los miembros de ICalculator, devuelva los resultados de los cálculos pertinentes.
En el código siguiente se muestra el complemento completado.
Imports System.AddIn Imports Calc1AddInView.CalcAddInViews Namespace CalcAddIns ' The AddInAttribute identifies this pipeline segment as an add-in. <AddIn("Calculator AddIn", Version:="1.0.0.0")> _ Public Class AddInCalcV1 Implements ICalculator Public Function Add(ByVal a As Double, ByVal b As Double) As Double _ Implements ICalculator.Add Return (a + b) End Function Public Function Subtract(ByVal a As Double, ByVal b As Double) As Double _ Implements ICalculator.Subtract Return (a - b) End Function Public Function Multiply(ByVal a As Double, ByVal b As Double) As Double _ Implements ICalculator.Multiply Return (a * b) End Function Public Function Divide(ByVal a As Double, ByVal b As Double) As Double _ Implements ICalculator.Divide Return (a / b) End Function End Class End Namespace
using System.Collections.Generic; using System.AddIn; using CalcAddInViews; namespace CalcAddIns { // The AddInAttribute identifies this pipeline segment as an add-in. [AddIn("Calculator AddIn",Version="1.0.0.0")] public class AddInCalcV1 : ICalculator { public double Add(double a, double b) { return a + b; } public double Subtract(double a, double b) { return a - b; } public double Multiply(double a, double b) { return a * b; } public double Divide(double a, double b) { return a / b; } } }
De manera opcional, compile la solución de Visual Studio.
Implementar la canalización
Ya está listo para compilar 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 compilarían en las carpetas siguientes:
Proyecto
Ruta de acceso
AddInCalcV1
MyApp\Pipeline\AddIns\CalcV1
Calc1AddInSideAdapter
MyApp\Pipeline\AddInSideAdapters
Calc1AddInView
MyApp\Pipeline\AddInViews
Calc1Contract
MyApp\Pipeline\Contracts
Calc1Host
MyApp
Calc1HostSideAdapter
MyApp\Pipeline\HostSideAdapters
Calc1HVA
MyApp
Nota Si decidió poner 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.Vea los comentarios sobre los requisitos de los directorios de la canalización en Requisitos del desarrollo de canalizaciones.
Compile 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 instaló ninguna copia adicional de los ensamblados en carpetas equivocadas.
Nota Si no cambió Copia local a False en la referencia Calc1AddInView del proyecto AddInCalcV1, 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 el complemento.
Para ejecutar la aplicación host
En el símbolo del sistema, vaya al directorio de la aplicación y ejecute la aplicación host, Calc1Host.exe.
El host busca todos los complementos disponibles de su tipo y le solicita que seleccione un complemento. Escriba 1 para el único complemento disponible.
Escriba una ecuación para la calculadora, como 2 + 2. Debe dejar espacios entre los números y el operador.
Escriba exit y presione la tecla Entrar para cerrar la aplicación.
Vea también
Tareas
Tutorial: Habilitar la compatibilidad con versiones anteriores al cambiar el host
Tutorial: Pasar colecciones entre hosts y complementos
Conceptos
Requisitos del desarrollo de canalizaciones