Condividi tramite


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

Aggiornamento: Luglio 2008

In questa procedura dettagliata viene descritta la versione 2 della pipeline descritta in Procedura dettagliata: creazione di un'applicazione estendibile. Nella versione 2 sono incluse ulteriori funzionalità di calcolo fornite da una stringa con valori delimitati da virgole di operazioni aritmetiche supportate per l'host. L'host può quindi scegliere un'operazione e inviare un'equazione al componente aggiuntivo per l'esecuzione del calcolo.

La pipeline dispone di un nuovo host e un nuovo contratto. Per consentire alla versione 1 del componente aggiuntivo di interagire con un host e un contratto nuovi, nella pipeline è inclusa la visualizzazione del componente aggiuntivo utilizzata per la versione 1 e un adattatore sul lato componente aggiuntivo che converte i dati dalla visualizzazione del componente aggiuntivo precedente nel nuovo contratto. Nella figura seguente è illustrata la modalità di funzionamento di entrambi i componenti aggiuntivi con lo stesso host.

Nuovo host, componenti aggiuntivi precedenti

Scenario di pipeline: nuovo host, vecchi componenti aggiuntivi

Questa pipeline è descritta anche in Scenari con pipeline di componenti aggiuntivi.

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 che include adattatori per la nuova versione del componente aggiuntivo e per il componente aggiuntivo della versione 1.

  • Creazione dell'adattatore sul lato host.

  • Creazione dell'host.

  • Creazione del componente aggiuntivo.

  • Distribuzione della pipeline.

  • Esecuzione dell'applicazione host.

Nella procedura dettagliata viene inoltre illustrato l'utilizzo delle classi di base astratte per definire visualizzazioni e viene mostrato che tali visualizzazioni sono compatibili con le visualizzazioni definite dalle interfacce. L'utilizzo delle interfacce è consigliato.

Nota:

Parte del codice mostrato in questa procedura dettagliata contiene riferimenti a spazi dei nomi estranei. I passaggi della procedura dettagliata riflettono accuratamente i riferimenti richiesti in Visual Studio.

Nel sito Managed Extensibility and Add-In Framework di CodePlex (informazioni in lingua inglese) sono disponibili esempi di codice aggiuntivi e anteprime di tecnologie di clienti riguardanti strumenti di compilazione di pipeline per componenti aggiuntivi.

Prerequisiti

Per completare questa procedura dettagliata, è necessario disporre dei seguenti componenti:

  • Visual Studio.

  • La versione 1 della pipeline descritta in Procedura dettagliata: creazione di un'applicazione estendibile. Poiché nella versione 2 vengono utilizzati i segmenti di pipeline sviluppati nella versione 1, è necessario sviluppare e distribuire la pipeline versione 1 prima di eseguire i passaggi descritti in questo argomento.

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 Calc2Contract, basandolo sul modello Libreria di classi.

  2. Denominare la soluzione CalculatorV2.

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 creare la struttura di directory della pipeline

  • Se non lo si è ancora fatto, aggiungere la cartella CalcV2 alla struttura di cartelle della pipeline creata in Procedura dettagliata: creazione di un'applicazione estendibile. La cartella CalcV2 conterrà la nuova versione del componente aggiuntivo.

    Pipeline
      AddIns
        CalcV1
        CalcV2
      AddInSideAdapters
      AddInViews
      Contracts
      HostSideAdapters
    

    Non è necessario inserire la struttura di cartelle della pipeline nella cartella dell'applicazione; in queste procedure dettagliate viene fatto solo per motivi di praticità. Se nella prima procedura dettagliata si è inserita la struttura di cartelle della pipeline in un percorso diverso, seguire lo stesso modello anche per questa. Per informazioni sui requisiti di directory della pipeline, vedere Requisiti di sviluppo delle pipeline.

Creazione del contratto e delle visualizzazioni

Il segmento del contratto per questa pipeline definisce l'interfaccia ICalc2Contract che dispone dei due metodi seguenti:

  • Metodo GetAvailableOperations.

    Questo metodo restituisce una stringa delle operazioni matematiche supportate dal componente aggiuntivo per l'host. Nella versione 2 sono supportate cinque operazioni e questo metodo restituisce la stringa "+,-,*,/,**", dove "**" rappresenta l'operazione Pow.

    Nelle visualizzazioni del componente aggiuntivo e host questo metodo è denominato Operations anziché GetAvailableOperations.

    È possibile esporre i metodi nel contratto come proprietà delle visualizzazioni convertendo la chiamata al metodo in una proprietà dell'adattatore.

  • Metodo Operate.

    L'host chiama questo metodo per inviare un'equazione al componente aggiuntivo per l'esecuzione del calcolo e la restituzione del risultato.

Per creare il contratto

  1. Nella soluzione di Visual Studio denominata CalculatorV2 aprire il progetto Calc2Contract.

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

    System.AddIn.Contract.dll

    System.AddIn.dll

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

  4. Aggiungere un nuovo elemento al progetto, utilizzando il modello Interfaccia. Nella finestra di dialogo Aggiungi nuovo elemento, denominare l'interfaccia ICalc2Contract.

  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 il segmento del contratto. Questa interfaccia deve disporre dell'attributo 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);
        }
    }
    

Poiché la visualizzazione del componente aggiuntivo e la visualizzazione host condividono lo stesso codice, è 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 per la versione 2

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

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

  3. Rinominare la classe Calculator2.

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

  5. Impostare Calculator2 come classe abstract (classe MustInherit in Visual Basic).

  6. Utilizzare il codice seguente per questa visualizzazione del componente aggiuntivo. Questa classe deve disporre dell'attributo 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);
        }
    }
    

Per creare la visualizzazione host del componente aggiuntivo

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

  2. Rinominare la classe Calculator.

  3. Impostare Calculator come classe abstract (classe MustInherit in Visual Basic).

  4. Nel file di classe utilizzare il codice seguente per creare la visualizzazione host del componente aggiuntivo.

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

Per illustrare l'utilizzo del componente aggiuntivo della versione 1 con il nuovo host, la soluzione deve includere la visualizzazione del componente aggiuntivo creata per la versione 1 del componente aggiuntivo relativo alla calcolatrice.

Per aggiungere il progetto della visualizzazione del componente aggiuntivo per la versione 1

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla soluzione CalculatorV2.

  2. Fare clic su Aggiungi, quindi su Progetto esistente.

  3. Individuare le cartelle che contengono la soluzione CalculatorV1, quindi selezionare il file di progetto per il progetto Calc1AddInView.

Creazione dell'adattatore sul lato componente aggiuntivo

Questo adattatore sul lato componente aggiuntivo è costituito da due adattatori visualizzazione-contratto: uno per adattare la visualizzazione del componente aggiuntivo della versione 2 al contratto della versione 2 e uno per adattare la visualizzazione del componente aggiuntivo della versione 1 al contratto della versione 2.

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.

Per creare l'adattatore sul lato componente aggiuntivo

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

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

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Aggiungere riferimenti di progetto ai progetti seguenti:

    Calc2AddInView

    Calc2Contract

  4. Selezionare ogni riferimento a progetto e, per impedire che gli assembly a cui si fa riferimento vengano copiati nella cartella di compilazione locale, accedere a Proprietà e impostare Copia localmente su False. Gli assembly saranno situati nella directory della pipeline, come descritto nella procedura "Distribuzione della pipeline" più avanti in questa procedura dettagliata. 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 un riferimento 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 Calc2AddInView.CalcAddInViews e Calc2Contract.CalculatorContracts, a meno che siano stati disattivati gli spazi dei nomi predefiniti nei progetti di Visual Basic.

  8. Utilizzare il codice seguente per questo adattatore sul lato componente aggiuntivo. Il modello di implementazione è simile all'adattatore sul lato componente aggiuntivo per la versione 1, anche se l'interfaccia del contratto è molto diversa.

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

Per consentire alla versione 1 del componente aggiuntivo di comunicare con il nuovo host, la pipeline del componente aggiuntivo della versione 1 richiede un adattatore sul lato componente aggiuntivo per la conversione dei dati dalla visualizzazione del componente aggiuntivo precedente al nuovo contratto.

Per creare l'adattatore dalla versione 1 alla versione 2 sul lato componente aggiuntivo

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

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

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Aggiungere riferimenti di progetto ai progetti seguenti:

    Calc1AddInView

    Calc2Contract

  4. Selezionare ogni riferimento a progetto e, per impedire che gli assembly a cui si fa riferimento vengano copiati nella cartella di compilazione locale, accedere a Proprietà e 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 Calc2V1ViewToV2ContractAddInSideAdapter del progetto.

  6. Nel file di classe aggiungere un riferimento 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 Calc2Contract.CalculatorContracts, a meno che siano stati disattivati gli spazi dei nomi predefiniti nei progetti di Visual Basic. Notare che lo spazio dei nomi della visualizzazione proviene dalla versione 1 e il contratto dalla versione 2.

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

  9. Impostare la classe Calc2V1ViewToV2ContractAddInSideAdapter in modo che erediti ContractBase, che fornisce un'implementazione predefinita dell'interfaccia IContract e implementa l'interfaccia del contratto della versione 2 per la pipeline, ICalc2Contract.

  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 ICalc2Contract, chiamare i membri appropriati dell'istanza ICalculator passata al costruttore e restituire i risultati. A causa delle differenze tra le interfacce dei contratti delle versioni 1 e 2, è necessario disporre di un'istruzione switch (istruzioneSelect Case in Visual Basic) per adattare la visualizzazione (ICalculator) al contratto (ICalc2Contract).

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

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

Creazione dell'adattatore sul lato host

Questo adattatore sul lato host è costituito da un adattatore contratto-visualizzazione. Un adattatore contratto-visualizzazione è sufficiente per supportare entrambe le versioni del componente aggiuntivo, perché ogni adattatore sul lato componente aggiuntivo esegue la conversione dalla rispettiva visualizzazione al contratto della versione 2.

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 Calc2HostSideAdapter alla soluzione CalculatorV2, basandolo sul modello Libreria di classi.

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

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Aggiungere riferimenti di progetto ai progetti seguenti:

    Calc2Contract

    Calc2HVA

  4. Selezionare ogni riferimento a progetto e, per impedire che gli assembly a cui si fa riferimento vengano copiati nella cartella di compilazione locale, accedere a Proprietà e 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 Calc2HVA.CalcHVAs e Calc2Contract.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 adattatore sul lato host.

  9. Impostare la classe CalculatorContractToViewHostSideAdapter in modo che erediti la classe di base astratta che rappresenta la visualizzazione host del componente aggiuntivo: CalcHVAs.Calculator (Calc2HVA.CalcHVAs.Calculator in Visual Basic). Notare la differenza dalla versione 1, in cui la visualizzazione host del componente aggiuntivo è un'interfaccia.

  10. Aggiungere un costruttore pubblico che accetta il tipo di contratto della pipeline, ICalc2Contract. 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 importante:

    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. Quando si esegue l'override dei membri di Calculator, chiamare semplicemente i membri corrispondenti dell'istanza ICalc2Contract passata al costruttore e restituire i risultati. In questo modo il contratto (ICalc2Contract) viene adattato alla visualizzazione (Calculator).

    Nel codice seguente viene illustrato il segmento dell'adattatore sul lato host completato.

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

Creazione dell'host

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

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

  • Cercare i componenti aggiuntivi di tipo Calculator nella directory radice della pipeline specificata.

  • Richiedere all'utente di specificare il componente aggiuntivo da utilizzare. In questo esempio sono disponibili due componenti aggiuntivi.

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

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

Per creare l'host

  1. Aggiungere un nuovo progetto denominato MathHost2 alla soluzione CalculatorV2, basandolo sul modello Applicazione console.

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

  3. Aggiungere un riferimento di progetto al progetto Calc2HVA. Selezionare il riferimento a progetto e, per impedire che l'assembly a cui si fa riferimento venga copiato nella cartella di compilazione locale, accedere a Proprietà e 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) MathHost2.

  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 è Calc2HVA.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. Utilizzare il codice seguente per creare l'applicazione 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:

    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.

Creazione del componente aggiuntivo

Un componente aggiuntivo implementa i metodi specificati dalla visualizzazione del componente aggiuntivo. In questo componente aggiuntivo il metodo Operations restituisce una stringa con l'elenco delle operazioni matematiche supportate dal componente aggiuntivo. Il metodo Operate fornisce il codice per calcolare il risultato in base alla selezione dell'host di un'operazione e due numeri.

Per creare il componente aggiuntivo

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

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

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Aggiungere un riferimento di progetto al progetto Calc2AddInView. Selezionare il riferimento a progetto e, per impedire che l'assembly a cui si fa riferimento venga copiato nella cartella di compilazione locale, accedere a Proprietà e 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 SampleV2AddIn.

  5. Nel file di classe, aggiungere riferimenti agli spazi dei nomi System.AddIn e System.AddIn.Pipeline. System.AddIn.Pipeline è richiesto solo perché nel codice è incluso un esempio dell'attributo QualificationDataAttribute.

  6. Nel file di classe, aggiungere un riferimento allo spazio dei nomi per il segmento della visualizzazione del componente aggiuntivo della versione 2: CalcAddInViews (Calc2AddInView.CalcAddInViews in Visual Basic).

  7. Applicare l'attributo AddInAttribute alla classe SampleV2AddIn, per identificarla come componente aggiuntivo.

  8. Applicare l'attributo QualificationDataAttribute alla classe SampleV2AddIn e specificare le informazioni che l'host può recuperare da AddInToken. In questo caso, le informazioni suggeriscono che il componente aggiuntivo deve essere caricato nel proprio dominio applicazione. Vedere Procedura: utilizzare dati di qualificazione.

  9. Impostare la classe SampleV2AddIn in modo che erediti la classe di base astratta che rappresenta la visualizzazione del componente aggiuntivo: Calculator2.

  10. Eseguire l'override dei membri di Calculator2 e restituire i risultati dei calcoli appropriati.

    Nel codice seguente viene illustrato il componente aggiuntivo completato.

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

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:

    Progetto

    Percorso

    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:

    Se si è inserita la struttura di cartelle della pipeline in un percorso diverso dalla cartella dell'applicazione, è necessario modificare di conseguenza i percorsi mostrati nella tabella.

  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.

    Nota:

    Se Copia localmente non è stato impostato su False per il riferimento al progetto Calc2AddInView nel progetto AddInCalcV2, 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 i componenti aggiuntivi.

Per eseguire l'applicazione host

  1. Verificare che vengano distribuite entrambe le versioni del componente aggiuntivo.

  2. Al prompt dei comandi passare alla directory dell'applicazione ed eseguire l'applicazione host. In questo esempio l'applicazione host è MathHost2.exe.

  3. L'host cerca tutti i componenti aggiuntivi disponibili del tipo specificato e chiede all'utente di selezionarne uno. Immettere 1 o 2.

  4. Immettere un'equazione per la calcolatrice, ad esempio 2 + 2.

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

  6. Ripetere i passaggi 2-5 per eseguire l'altro componente aggiuntivo.

Vedere anche

Attività

Procedura dettagliata: creazione di un'applicazione estendibile

Procedura dettagliata: passaggio di insiemi tra host e componenti aggiuntivi

Concetti

Requisiti di sviluppo delle pipeline

Contratti, visualizzazioni e adattatori

Sviluppo pipeline

Cronologia delle modifiche

Date

History

Motivo

Luglio 2008

Errori corretti nel testo. Aggiunta una nota sul mantenimento di un riferimento al contratto.

Commenti e suggerimenti dei clienti.