Procedura dettagliata: creazione di un'applicazione estendibile

In questa procedura dettagliata viene descritto come creare una pipeline per un componente aggiuntivo che esegue semplici funzioni di calcolo. Non viene illustrato uno scenario realistico, bensì la funzionalità di base di una pipeline e il modo in cui un componente aggiuntivo può fornire servizi per un host.

In questa procedura dettagliata vengono descritte le attività seguenti:

  • Creazione di una soluzione di Visual Studio.

  • Creazione della struttura di directory della pipeline.

  • Creazione del contratto e delle visualizzazioni.

  • Creazione dell'adattatore sul lato componente aggiuntivo.

  • Creazione dell'adattatore sul lato host.

  • Creazione dell'host.

  • Creazione del componente aggiuntivo.

  • Distribuzione della pipeline.

  • Esecuzione dell'applicazione host.

Questa pipeline passa solo tipi serializzabili, Double e String, tra l'host e il componente aggiuntivo. Per un esempio che illustra come passare insiemi di tipi di dati complessi, vedere Procedura dettagliata: passaggio di insiemi tra host e componenti aggiuntivi.

Il contratto per questa pipeline definisce un modello a oggetti di quattro operazioni aritmetiche: addizione, sottrazione, moltiplicazione e divisione. L'host fornisce al componente aggiuntivo un'equazione da calcolare, ad esempio 2 + 2, e il componente aggiuntivo restituisce il risultato all'host.

Nella versione 2 del componente aggiuntivo della calcolatrice vengono fornite maggiori possibilità di calcolo e viene dimostrato il controllo delle versioni. Queste operazioni vengono descritte in Procedura dettagliata: abilitazione della compatibilità con le versioni precedenti in base alle modifiche dell'host.

NotaNota

Per ulteriori esempi di codice e anteprime di tecnologie di clienti riguardanti strumenti di creazione di pipeline per componenti aggiuntivi, vedere Managed Extensibility and Add-In Framework on CodePlex (informazioni in lingua inglese).

Prerequisiti

Per completare questa procedura dettagliata, sono necessari i seguenti elementi:

  • Visual Studio.

Creazione di una soluzione di Visual Studio

Per contenere i progetti dei segmenti di pipeline, utilizzare una soluzione di Visual Studio.

Per creare la soluzione della pipeline

  1. In Visual Studio creare un nuovo progetto denominato Calc1Contract, basandolo sul modello Libreria di classi.

  2. Denominare la soluzione CalculatorV1.

Creazione della struttura di directory della pipeline

Il modello del componente aggiuntivo richiede che gli assembly dei segmenti di pipeline siano inseriti in una struttura di directory specificata. Per ulteriori informazioni sulla struttura della pipeline, vedere Requisiti di sviluppo delle pipeline.

Per creare la struttura di directory della pipeline

  1. Creare una cartella di applicazione in un qualsiasi percorso del computer.

  2. In tale cartella creare la struttura seguente:

    Pipeline
      AddIns
        CalcV1
        CalcV2
      AddInSideAdapters
      AddInViews
      Contracts
      HostSideAdapters
    

    Non è necessario inserire la struttura di cartelle della pipeline nella cartella dell'applicazione; in questa procedura viene fatto solo per motivi di praticità. Nel passaggio appropriato della procedura dettagliata viene illustrato come modificare il codice se la struttura di cartelle della pipeline è in un percorso diverso. Per informazioni sui requisiti di directory della pipeline, vedere Requisiti di sviluppo delle pipeline.

    NotaNota

    La cartella CalcV2 non viene utilizzata in questa procedura dettagliata; è un segnaposto per Procedura dettagliata: abilitazione della compatibilità con le versioni precedenti in base alle modifiche dell'host.

Creazione del contratto e delle visualizzazioni

Il segmento del contratto per questa pipeline definisce l'interfaccia ICalc1Contract, che a sua volta definisce quattro metodi: add, subtract, multiply e divide.

Per creare il contratto

  1. Nella soluzione di Visual Studio denominata CalculatorV1 aprire il progetto Calc1Contract.

  2. In Esplora soluzioni aggiungere riferimenti ai seguenti assembly per il progetto Calc1Contract.

    System.AddIn.Contract.dll

    System.AddIn.dll

  3. In Esplora soluzioni, escludere la classe predefinita aggiunta ai nuovi progetti Libreria di classi.

  4. In Esplora soluzioni aggiungere un nuovo elemento al progetto utilizzando il modello Interfaccia. Nella finestra di dialogo Aggiungi nuovo elemento, denominare l'interfaccia ICalc1Contract.

  5. Nel file di interfaccia aggiungere i riferimenti agli spazi dei nomi System.AddIn.Contract e System.AddIn.Pipeline.

  6. Utilizzare il codice seguente per completare questo segmento del contratto. Questa interfaccia deve disporre dell'attributo 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);
        }
    }
    
  7. Facoltativamente, compilare la soluzione di Visual Studio. La soluzione non può essere eseguita sino alla procedura finale, ma la compilazione al termine di ogni procedura assicura che ogni progetto sia corretto.

Poiché la visualizzazione del componente aggiuntivo e la visualizzazione host del componente aggiuntivo condividono in genere lo stesso codice, particolarmente nella prima versione del componente aggiuntivo, è possibile crearle con facilità contemporaneamente. Tali visualizzazioni differiscono per un solo fattore: la visualizzazione del componente aggiuntivo richiede l'attributo AddInBaseAttribute, mentre la visualizzazione host del componente aggiuntivo non richiede attributi.

Per creare la visualizzazione del componente aggiuntivo

  1. Aggiungere un nuovo progetto denominato Calc1AddInView alla soluzione CalculatorV1, basandolo sul modello Libreria di classi.

  2. In Esplora soluzioni aggiungere un riferimento a System.AddIn.dll per il progetto Calc1AddInView.

  3. In Esplora soluzioni, escludere la classe predefinita aggiunta ai nuovi progetti Libreria di classi e aggiungere un nuovo elemento al progetto utilizzando il modello Interfaccia. Nella finestra di dialogo Aggiungi nuovo elemento, denominare l'interfaccia ICalculator.

  4. Nel file di interfaccia aggiungere un riferimento allo spazio dei nomi System.AddIn.Pipeline.

  5. Utilizzare il codice seguente per completare questa visualizzazione del componente aggiuntivo. Questa interfaccia deve disporre dell'attributo 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);
        }
    }
    
  6. Facoltativamente, compilare la soluzione di Visual Studio.

Per creare la visualizzazione host del componente aggiuntivo

  1. Aggiungere un nuovo progetto denominato Calc1HVA alla soluzione CalculatorV1, basandolo sul modello Libreria di classi.

  2. In Esplora soluzioni, escludere la classe predefinita aggiunta ai nuovi progetti Libreria di classi e aggiungere un nuovo elemento al progetto utilizzando il modello Interfaccia. Nella finestra di dialogo Aggiungi nuovo elemento, denominare l'interfaccia ICalculator.

  3. Nel file di interfaccia utilizzare il codice seguente per completare questa visualizzazione host del componente aggiuntivo.

    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);
        }
    }
    
  4. Facoltativamente, compilare la soluzione di Visual Studio.

Creazione dell'adattatore sul lato componente aggiuntivo

Questo adattatore sul lato componente aggiuntivo è costituito da un adattatore visualizzazione-contratto. Questo segmento della pipeline converte i tipi dalla visualizzazione del componente aggiuntivo nel contratto.

In questa pipeline il componente aggiuntivo fornisce un servizio all'host e il flusso dei tipi passa dal componente aggiuntivo all'host. Poiché non vengono passati tipi dall'host al componente aggiuntivo, non è necessario includere un adattatore contratto-visualizzazione sul lato componente aggiuntivo di questa pipeline.

Per creare l'adattatore sul lato componente aggiuntivo

  1. Aggiungere un nuovo progetto denominato Calc1AddInSideAdapter alla soluzione CalculatorV1, basandolo sul modello Libreria di classi.

  2. In Esplora soluzioni aggiungere riferimenti ai seguenti assembly per il progetto Calc1AddInSideAdapter.

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Aggiungere riferimenti ai progetti per i segmenti della pipeline adiacenti:

    Calc1AddInView

    Calc1Contract

  4. Selezionare ogni riferimento al progetto e in Proprietà impostare Copia localmente su False. In Visual Basic, utilizzare la scheda Riferimenti di Proprietà progetti per impostare Copia localmente su False per i due riferimenti al progetto.

  5. Rinominare la classe predefinita CalculatorViewToContractAddInSideAdapter del progetto.

  6. Nel file di classe aggiungere i riferimenti allo spazio dei nomi System.AddIn.Pipeline.

  7. Nel file di classe aggiungere i riferimenti agli spazi dei nomi per i segmenti adiacenti: CalcAddInViews e CalculatorContracts. In Visual Basic, questi riferimenti agli spazi dei nomi sono Calc1AddInView.CalcAddInViews e Calc1Contract.CalculatorContracts, a meno che siano stati disattivati gli spazi dei nomi predefiniti nei progetti di Visual Basic.

  8. Applicare l'attributo AddInAdapterAttribute alla classe CalculatorViewToContractAddInSideAdapter, per identificarla come adattatore sul lato componente aggiuntivo.

  9. Impostare la classe CalculatorViewToContractAddInSideAdapter in modo che erediti ContractBase, che fornisce un'implementazione predefinita dell'interfaccia IContract e implementa l'interfaccia del contratto per la pipeline, ICalc1Contract.

  10. Aggiungere un costruttore pubblico che accetta ICalculator, lo memorizza nella cache in un campo privato e chiama il costruttore della classe di base.

  11. Per implementare i membri di ICalc1Contract, chiamare semplicemente i membri corrispondenti dell'istanza ICalculator passata al costruttore e restituire i risultati. In questo modo la visualizzazione (ICalculator) viene adattata al contratto (ICalc1Contract).

    Nel codice seguente viene illustrato l'adattatore sul lato componente aggiuntivo completato.

    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);
            }
        }
    }
    
  12. Facoltativamente, compilare la soluzione di Visual Studio.

Creazione dell'adattatore sul lato host

Questo adattatore sul lato host è costituito da un adattatore contratto-visualizzazione. Questo segmento adatta il contratto alla visualizzazione host del componente aggiuntivo.

In questa pipeline il componente aggiuntivo fornisce un servizio all'host e il flusso dei tipi passa dal componente aggiuntivo all'host. Poiché non vengono passati tipi dall'host al componente aggiuntivo, non è necessario includere un adattatore visualizzazione-contratto.

Per implementare gestione della durata, utilizzare un oggetto ContractHandle per connettere un token di durata al contratto. È necessario mantenere un riferimento a questo handle affinché la gestione della durata funzioni. Dopo l'applicazione del token non è necessaria un'ulteriore fase di programmazione perché il sistema dei componenti aggiuntivi può eliminare gli oggetti quando non vengono più utilizzati, rendendoli disponibili per l'operazione di Garbage Collection. Per ulteriori informazioni, vedere Gestione della durata.

Per creare l'adattatore sul lato host

  1. Aggiungere un nuovo progetto denominato Calc1HostSideAdapter alla soluzione CalculatorV1, basandolo sul modello Libreria di classi.

  2. In Esplora soluzioni aggiungere riferimenti ai seguenti assembly per il progetto Calc1HostSideAdapter.

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Aggiungere riferimenti ai progetti per i segmenti adiacenti:

    Calc1Contract

    Calc1HVA

  4. Selezionare ogni riferimento al progetto e in Proprietà impostare Copia localmente su False. In Visual Basic, utilizzare la scheda Riferimenti di Proprietà progetti per impostare Copia localmente su False per i due riferimenti al progetto.

  5. Rinominare la classe predefinita CalculatorContractToViewHostSideAdapter del progetto.

  6. Nel file di classe aggiungere i riferimenti allo spazio dei nomi System.AddIn.Pipeline.

  7. Nel file di classe aggiungere i riferimenti agli spazi dei nomi per i segmenti adiacenti: CalcHVAs e CalculatorContracts. In Visual Basic, questi riferimenti agli spazi dei nomi sono Calc1HVA.CalcHVAs e Calc1Contract.CalculatorContracts, a meno che siano stati disattivati gli spazi dei nomi predefiniti nei progetti di Visual Basic.

  8. Applicare l'attributo HostAdapterAttribute alla classe CalculatorContractToViewHostSideAdapter, per identificarla come segmento dell'adattatore sul lato host.

  9. Impostare la classe CalculatorContractToViewHostSideAdapter in modo che implementi l'interfaccia che rappresenta la visualizzazione host del componente aggiuntivo: Calc1HVAs.ICalculator (Calc1HVA.CalcHVAs.ICalculator in Visual Basic).

  10. Aggiungere un costruttore pubblico che accetta il tipo di contratto della pipeline, ICalc1Contract. Il costruttore deve memorizzare nella cache il riferimento al contratto. Deve inoltre creare e memorizzare nella cache un nuovo oggetto ContractHandle per il contratto, per gestire la durata del componente aggiuntivo.

    Nota importanteImportante

    L'oggetto ContractHandle è di importanza fondamentale nella gestione della durata.Se non si riesce a mantenere un riferimento all'oggetto ContractHandle, quest'ultimo verrà recuperato dalla Garbage Collection e la pipeline verrà interrotta in un momento non previsto dal programma.Ciò può comportare errori difficili da diagnosticare, ad esempio AppDomainUnloadedException.L'arresto è una fase normale del ciclo di vita di una pipeline. Pertanto, non esiste alcun modo in cui il codice di gestione della durata sia in grado di rilevare questa condizione come un errore.

  11. Per implementare i membri di ICalculator, chiamare semplicemente i membri corrispondenti dell'istanza ICalc1Contract passata al costruttore e restituire i risultati. In questo modo il contratto (ICalc1Contract) viene adattato alla visualizzazione (ICalculator).

    Nel codice seguente viene illustrato l'adattatore sul lato host completato.

    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);
            }
        }
    }
    
  12. Facoltativamente, compilare la soluzione di Visual Studio.

Creazione dell'host

Un'applicazione host interagisce con il componente aggiuntivo tramite la visualizzazione host del componente aggiuntivo. Utilizza i metodi di individuazione e attivazione del componente aggiuntivo forniti dalle classi AddInStore e AddInToken per effettuare le operazioni seguenti:

  • Aggiornare la cache di informazioni sulla pipeline e sui componenti aggiuntivi.

  • Trovare i componenti aggiuntivi del tipo di visualizzazione host, ICalculator, nella directory radice della pipeline specificata.

  • Richiedere all'utente di specificare il componente aggiuntivo da utilizzare.

  • Attivare il componente aggiuntivo selezionato in un nuovo dominio applicazione con un livello di attendibilità della sicurezza specificato.

  • Eseguire il metodo personalizzato RunCalculator che chiama i metodi del componente aggiuntivo specificati dalla visualizzazione host del componente aggiuntivo.

Per creare l'host

  1. Aggiungere un nuovo progetto denominato Calc1Host alla soluzione CalculatorV1, basandolo sul modello Applicazione console.

  2. In Esplora soluzioni aggiungere un riferimento all'assembly System.AddIn.dll per il progetto Calc1Host.

  3. Aggiungere un riferimento di progetto al progetto Calc1HVA. Selezionare il riferimento al progetto e in Proprietà impostare Copia localmente su False. In Visual Basic, utilizzare la scheda Riferimenti di Proprietà progetti per impostare Copia localmente su False.

  4. Rinominare il file di classe (il modulo in Visual Basic) MathHost1.

  5. In Visual Basic, utilizzare la scheda Applicazione della finestra di dialogo Proprietà progetti per impostare Oggetto di avvio su Sub Main.

  6. Nel file di classe o di modulo aggiungere un riferimento allo spazio dei nomi System.AddIn.Hosting.

  7. Nel file di classe o di modulo, aggiungere un riferimento allo spazio dei nomi per la visualizzazione host del componente aggiuntivo: CalcHVAs. In Visual Basic, questo riferimento allo spazio dei nomi è Calc1HVA.CalcHVAs, a meno che siano stati disattivati gli spazi dei nomi predefiniti nei progetti di Visual Basic.

  8. In Esplora soluzioni selezionare la soluzione, quindi scegliere Proprietà dal menu Progetto. Nella finestra di dialogo Pagine delle proprietà di Soluzione impostare Progetto di avvio singolo in modo che venga utilizzato come progetto di questa applicazione host.

  9. Nel file di classe o di modulo, utilizzare il metodo AddInStore.Update per aggiornare la cache. Utilizzare il metodo AddInStore.FindAddIn per ottenere un insieme di token e il metodo AddInToken.Activate per attivare un componente aggiuntivo.

    Nel codice seguente viene illustrata l'applicazione host completata.

    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; }
            }
        }
    }
    
    NotaNota

    In questo codice si presuppone che la struttura di cartelle della pipeline si trovi nella cartella dell'applicazione.Se si trova in percorso diverso, modificare la riga di codice che imposta la variabile addInRoot, in modo che la variabile contenga il percorso della struttura di directory della pipeline.

    Nel codice viene utilizzato un metodo ChooseCalculator per elencare i token e richiedere all'utente di scegliere un componente aggiuntivo. Il metodo RunCalculator richiede all'utente semplici espressioni matematiche, analizza le espressioni utilizzando la classe Parser e visualizza i risultati restituiti dal componente aggiuntivo.

  10. Facoltativamente, compilare la soluzione di Visual Studio.

Creazione del componente aggiuntivo

Un componente aggiuntivo implementa i metodi specificati dalla visualizzazione del componente aggiuntivo. Questo componente aggiuntivo implementa le operazioni Add, Subtract, Multiply e Divide e restituisce i risultati all'host.

Per creare il componente aggiuntivo

  1. Aggiungere un nuovo progetto denominato AddInCalcV1 alla soluzione CalculatorV1, basandolo sul modello Libreria di classi.

  2. In Esplora soluzioni aggiungere un riferimento all'assembly System.AddIn.dll per il progetto.

  3. Aggiungere un riferimento al progetto Calc1AddInView. Selezionare il riferimento al progetto e in Proprietà impostare Copia localmente su False. In Visual Basic, utilizzare la scheda Riferimenti di Proprietà progetti per impostare Copia localmente su False per il riferimento al progetto.

  4. Rinominare la classe AddInCalcV1.

  5. Nel file di classe, aggiungere un riferimento allo spazio dei nomi System.AddIn e il segmento della visualizzazione del componente aggiuntivo: CalcAddInViews (Calc1AddInView.CalcAddInViews in Visual Basic).

  6. Applicare l'attributo AddInAttribute alla classe AddInCalcV1, per identificarla come componente aggiuntivo.

  7. Impostare la classe AddInCalcV1 in modo che implementi l'interfaccia che rappresenta la visualizzazione del componente aggiuntivo: CalcAddInViews.ICalculator (Calc1AddInView.CalcAddInViews.ICalculator in Visual Basic).

  8. Implementare i membri di ICalculator restituendo i risultati dei calcoli appropriati.

    Nel codice seguente viene illustrato il componente aggiuntivo completato.

    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;
            }
        }
    }
    
  9. Facoltativamente, compilare la soluzione di Visual Studio.

Distribuzione della pipeline

A questo punto è possibile procedere alla compilazione e distribuzione dei segmenti del componente aggiuntivo alla struttura di directory della pipeline richiesta.

Per distribuire i segmenti alla pipeline

  1. Per ogni progetto nella soluzione, utilizzare la scheda Compilazione di Proprietà progetto (la scheda Compilazione anche in Visual Basic) per impostare il valore di Percorso output (Percorso dell'output di compilazione in Visual Basic). Se, ad esempio, si è denominata la cartella dell'applicazione MyApp, i progetti saranno compilati nelle cartelle seguenti:

    Project

    Percorso

    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

    NotaNota

    Se si è deciso di inserire la struttura di cartelle della pipeline in un percorso diverso dalla cartella dell'applicazione, è necessario modificare di conseguenza i percorsi mostrati nella tabella.Per informazioni sui requisiti di directory della pipeline, vedere Requisiti di sviluppo delle pipeline.

  2. Compilare la soluzione di Visual Studio.

  3. Controllare nelle directory dell'applicazione e della pipeline che gli assembly siano stati copiati nelle directory corrette e che non siano state installate copie supplementari degli assembly nelle cartelle errate.

    NotaNota

    Se Copia localmente non è stato impostato su False per il riferimento al progetto Calc1AddInView nel progetto AddInCalcV1, problemi di contesto del caricatore impediranno l'individuazione del componente aggiuntivo.

    Per ulteriori informazioni sulla distribuzione alla pipeline, vedere Requisiti di sviluppo delle pipeline.

Esecuzione dell'applicazione host

A questo punto è possibile eseguire l'host e interagire con il componente aggiuntivo.

Per eseguire l'applicazione host

  1. Al prompt dei comandi, passare alla directory dell'applicazione ed eseguire l'applicazione host, Calc1Host.exe.

  2. L'host trova tutti i componenti aggiuntivi disponibili del tipo specificato e chiede all'utente di selezionarne uno. Immettere 1 per il solo componente aggiuntivo disponibile.

  3. Immettere un'equazione per la calcolatrice, ad esempio 2 + 2. Tra i numeri e l'operatore devono essere presenti spazi.

  4. Digitare exit e premere INVIO per chiudere l'applicazione.

Vedere anche

Attività

Procedura dettagliata: abilitazione della compatibilità con le versioni precedenti in base alle modifiche dell'host

Procedura dettagliata: passaggio di insiemi tra host e componenti aggiuntivi

Concetti

Requisiti di sviluppo delle pipeline

Contratti, visualizzazioni e adattatori

Sviluppo pipeline