Exemplarische Vorgehensweise: Aktivieren der Abwärtskompatibilität bei geändertem Host

Aktualisiert: Juli 2008

Diese exemplarische Vorgehensweise beschreibt Version 2 der Pipeline, die in Exemplarische Vorgehensweise: Erstellen von erweiterbaren Anwendungen beschrieben wird. Version 2 enthält zusätzliche Berechnungsfunktionen, indem eine durch Trennzeichen getrennte Zeichenfolge arithmetischer Operationen mit Unterstützung für den Host bereitgestellt wird. Der Host kann dann eine Operation auswählen und eine Formel zur Berechnung durch das Add-In übermitteln.

Die Pipeline weist einen neuen Host und einen neuen Vertrag auf. Damit Version 1 des Add-Ins mit einem neuen Host und Vertrag funktioniert, enthält die Pipeline die für Version 1 verwendete Add-In-Ansicht sowie einen Add-In-seitigen Adapter, der die Daten aus der älteren Add-In-Ansicht in den neuen Vertrag umwandelt. In der folgenden Abbildung wird verdeutlicht, wie beide Add-Ins mit demselben Host zusammenarbeiten können.

Neuer Host, alte Add-Ins

Diese Pipeline wird auch in Szenarien für Add-In-Pipelines beschrieben.

Diese exemplarische Vorgehensweise erläutert die folgenden Aufgaben:

  • Erstellen einer Visual Studio-Projektmappe

  • Erstellen der Pipelineverzeichnisstruktur

  • Erstellen des Vertrags und der Ansichten

  • Erstellen des Add-In-seitigen Adapters, der Adapter für die neue Add-In-Version und für das Add-In aus Version 1 enthält.

  • Erstellen des hostseitigen Adapters

  • Erstellen des Hosts

  • Erstellen des Add-Ins

  • Bereitstellen der Pipeline

  • Ausführen der Hostanwendung

Außerdem wird die Verwendung abstrakter Basisklassen zum Definieren von Ansichten veranschaulicht. Es wird gezeigt, dass diese Ansichten kompatibel zu Ansichten sind, die durch Schnittstellen definiert werden. Es wird empfohlen, Schnittstellen zu verwenden.

Hinweis:

Ein Teil des Codes, der in dieser exemplarischen Vorgehensweise verwendet wird, enthält externe Namespaceverweise. Die Schritte der exemplarischen Vorgehensweise entsprechen genau den Verweisen, die in Visual Studio erforderlich sind.

Zusätzlichen Beispielcode und Community Technology Previews von Tools für die Erstellung von Add-In-Pipelines finden Sie auf der Managed Extensibility and Add-In Framework-Website auf CodePlex.

Vorbereitungsmaßnahmen

Zum Durchführen dieser exemplarischen Vorgehensweise benötigen Sie die folgenden Komponenten:

Erstellen einer Visual Studio-Projektmappe

Verwenden Sie eine Projektmappe in Visual Studio, die die Projekte der Pipelinesegmente enthalten soll.

So erstellen Sie die Pipelineprojektmappe

  1. Erstellen Sie in Visual Studio ein neues Projekt mit dem Namen Calc2Contract. Verwenden Sie als Basis die Vorlage Klassenbibliothek.

  2. Geben Sie der Projektmappe den Namen CalculatorV2.

Erstellen der Pipelineverzeichnisstruktur

Das Add-In-Modell erfordert, dass die Pipelinesegmentassemblys in einer angegebenen Verzeichnisstruktur angeordnet werden.

So erstellen Sie die Pipelineverzeichnisstruktur

  • Wenn Sie dies noch nicht getan haben, fügen Sie den Ordner CalcV2 zur Pipelineordnerstruktur hinzu, die Sie in der Exemplarische Vorgehensweise: Erstellen von erweiterbaren Anwendungen erstellt haben. Der Ordner CalcV2 enthält die neue Version des Add-Ins.

    Pipeline
      AddIns
        CalcV1
        CalcV2
      AddInSideAdapters
      AddInViews
      Contracts
      HostSideAdapters
    

    Der Anwendungsordner muss nicht notwendigerweise die Struktur des Pipelineordners aufweisen. Dies wird in diesen exemplarischen Vorgehensweisen nur aus praktischen Gründen durchgeführt. Wenn Sie in der ersten exemplarischen Vorgehensweise die Struktur des Pipelineordners in einem anderen Speicherort gespeichert haben, gehen Sie in dieser exemplarischen Vorgehensweise entsprechend vor. Weitere Informationen finden Sie in den Ausführungen zu den Anforderungen von Pipelineverzeichnissen unter Anforderungen für die Pipelineentwicklung.

Erstellen des Vertrags und der Ansichten

Das Vertragssegment für diese Pipeline definiert die ICalc2Contract-Schnittstelle, die die folgenden beiden Methoden enthält:

  • Die GetAvailableOperations-Methode

    Diese Methode gibt eine Zeichenfolge der mathematischen Operationen zurück, die das Add-In für den Host unterstützt. Version 2 unterstützt fünf Operationen, und diese Methode gibt die Zeichenfolge "+,-,*,/,**" zurück, wobei "**" die Pow-Operation darstellt.

    In der Add-In-Ansicht und der Hostansicht hat diese Methode die Bezeichnung Operations anstelle von GetAvailableOperations.

    Sie können Methoden im Vertrag als Eigenschaften für die Ansichten verfügbar machen, indem Sie den Methodenaufruf in eine Eigenschaft im Adapter umwandeln.

  • Die Operate-Methode

    Der Host ruft diese Methode auf, um eine Formel für das Add-In bereitzustellen, sodass das Add-In die Berechnung ausführen und das Ergebnis zurückgeben kann.

So erstellen Sie den Vertrag

  1. Öffnen Sie in der Visual Studio-Projektmappe CalculatorV2 das Calc2Contract-Projekt.

  2. Fügen Sie im Projektmappen-Explorer Verweise auf die folgenden Assemblys dem Calc2Contract-Projekt hinzu:

    System.AddIn.Contract.dll

    System.AddIn.dll

  3. Schließen Sie im Projektmappen-Explorer die Standardklasse aus, die neuen Klassenbibliotheksprojekten hinzugefügt wird.

  4. Fügen Sie dem Projekt mit der Schnittstelle-Vorlage ein neues Element hinzu. Geben Sie der Schnittstelle im Dialogfeld Neues Element hinzufügen den Namen ICalc2Contract.

  5. Fügen Sie in der Schnittstellendatei Namespaceverweise auf System.AddIn.Contract und auf System.AddIn.Pipeline hinzu.

  6. Verwenden Sie den folgenden Code, um dieses Vertragssegment fertig zu stellen. Beachten Sie, dass diese Schnittstelle das AddInContractAttribute-Attribut aufweisen muss.

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

Da die Add-In-Ansicht und die Hostansicht denselben Code enthalten, können Sie die Ansichten mühelos zur selben Zeit erstellen. Sie unterscheiden sich lediglich in einem Aspekt: Die Add-In-Ansicht erfordert das AddInBaseAttribute-Attribut, während die Hostansicht des Add-Ins keine Attribute erfordert.

So erstellen Sie die Add-In-Ansicht für Version 2

  1. Fügen Sie der CalculatorV2-Projektmappe ein neues Projekt mit dem Namen Calc2AddInView hinzu. Verwenden Sie die Klassenbibliothek-Vorlage als Grundlage.

  2. Fügen Sie im Projektmappen-Explorer dem Calc2AddInView-Projekt einen Verweis auf System.AddIn.dll hinzu.

  3. Benennen Sie die Klasse in Calculator2 um.

  4. Fügen Sie in der Klassendatei einen Namespaceverweis auf System.AddIn.Pipeline hinzu.

  5. Legen Sie Calculator2 als abstract-Klasse fest (MustInherit-Klasse in Visual Basic).

  6. Verwenden Sie den folgenden Code für diese Add-In-Ansicht. Beachten Sie, dass diese Klasse das AddInBaseAttribute-Attribut aufweisen muss.

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

So erstellen Sie die Hostansicht des Add-Ins

  1. Fügen Sie der CalculatorV2-Projektmappe ein neues Projekt mit dem Namen Calc2HVA hinzu. Verwenden Sie die Klassenbibliothek-Vorlage als Grundlage.

  2. Benennen Sie die Klasse in Calculator um.

  3. Legen Sie Calculator als abstract-Klasse fest (MustInherit-Klasse in Visual Basic).

  4. Verwenden Sie in der Klassendatei den folgenden Code, um die Hostansicht des Add-Ins zu erstellen.

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

Um die Verwendung von Version 1 des Add-Ins mit dem neuen Host zu veranschaulichen, muss die Projektmappe die Add-In-Ansicht, die für Version 1 des Rechner-Add-Ins erstellt wurde, enthalten.

So fügen Sie das Add-In-Ansichtsprojekt aus Version 1 hinzu

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die CalculatorV2-Projektmappe.

  2. Klicken Sie auf Hinzufügen und dann auf Vorhandenes Projekt.

  3. Gehen Sie zu den Ordnern, die die CalculatorV1-Projektmappe enthalten, und wählen Sie die Projektdatei für das Calc1AddInView-Projekt aus.

Erstellen des Add-In-seitigen Adapters

Dieser Add-In-seitige Adapter besteht aus zwei Ansicht-zu-Vertrag-Adaptern: Ein Adapter dient zum Anpassen von Version 2 der Add-In-Ansicht an Version 2 des Vertrags, der andere Adapter dient zum Anpassen von Version 1 der Add-In-Ansicht an Version 2 des Vertrags.

In dieser Pipeline stellt das Add-In einen Dienst für den Host bereit, und die Typen fließen vom Add-In zum Host. Da keine Typen vom Host zum Add-In fließen, müssen Sie keinen Ansicht-zu-Vertrag-Adapter aufnehmen.

So erstellen Sie den Add-In-seitigen Adapter

  1. Fügen Sie der Projektmappe CalculatorV2 ein neues Projekt mit dem Namen Calc2AddInSideAdapter hinzu. Verwenden Sie die Klassenbibliothek-Vorlage als Grundlage.

  2. Fügen Sie im Projektmappen-Explorer dem Calc2AddInSideAdapter-Projekt Verweise auf die folgenden Assemblys hinzu:

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Fügen Sie den folgenden Projekten Projektverweise hinzu:

    Calc2AddInView

    Calc2Contract

  4. Wählen Sie die einzelnen Projektverweise aus, und legen Sie unter Eigenschaften die Option Lokale Kopie auf False fest, damit die Assemblys, auf die verwiesen wird, nicht in den lokalen Buildordner kopiert werden. Die Assemblys befinden sich, wie weiter unten in "Bereitstellen der Pipeline" beschrieben, im Pipelineverzeichnis. In Visual Basic kann unter Projekteigenschaften auf der Registerkarte Verweise die Option Lokale Kopie auf False festgelegt werden.

  5. Benennen Sie die Standardklasse des Projekts in CalculatorViewToContractAddInSideAdapter um.

  6. Fügen Sie in der Klassendatei einen Namespaceverweis auf System.AddIn.Pipeline hinzu.

  7. Fügen Sie in der Klassendatei Namespaceverweise für die benachbarten Segmente hinzu: CalcAddInViews und CalculatorContracts. (In Visual Basic lauten die entsprechenden Namespaceverweise Calc2AddInView.CalcAddInViews und Calc2Contract.CalculatorContracts, sofern der Standardnamespace für Visual Basic-Projekte nicht deaktiviert wurde.)

  8. Verwenden Sie den folgenden Code für diesen Add-In-seitigen Adapter. Das Implementierungsmuster ähnelt dem Add-In-seitigen Adapter für Version 1, obwohl die Vertragsschnittstelle erheblich abweicht.

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

Damit Version 1 des Add-Ins mit dem neuen Host kommunizieren kann, erfordert die Pipeline für Version 1 des Add-Ins einen Add-In-seitigen Adapter, der die Daten aus der alten Add-In-Ansicht in den neuen Vertrag umwandelt.

So erstellen Sie den Add-In-seitigen Adapter für die Umwandlung aus Version 1 in Version 2

  1. Fügen Sie der CalculatorV2-Projektmappe ein neues Projekt mit dem Namen Calc2V1toV2AddInSideAdapter hinzu. Verwenden Sie die Klassenbibliothek-Vorlage als Grundlage.

  2. Fügen Sie im Projektmappen-Explorer dem Calc2V1toV2AddInSideAdapter-Projekt Verweise auf die folgenden Assemblys hinzu:

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Fügen Sie den folgenden Projekten Projektverweise hinzu:

    Calc1AddInView

    Calc2Contract

  4. Wählen Sie die einzelnen Projektverweise aus, und legen Sie unter Eigenschaften die Option Lokale Kopie auf False fest, damit die Assemblys, auf die verwiesen wird, nicht in den lokalen Buildordner kopiert werden. In Visual Basic kann unter Projekteigenschaften auf der Registerkarte Verweise die Option Lokale Kopie auf False festgelegt werden.

  5. Benennen Sie die Standardklasse des Projekts in Calc2V1ViewToV2ContractAddInSideAdapter um.

  6. Fügen Sie in der Klassendatei einen Namespaceverweis auf System.AddIn.Pipeline hinzu.

  7. Fügen Sie in der Klassendatei Namespaceverweise für die benachbarten Segmente hinzu: CalcAddInViews und CalculatorContracts. (In Visual Basic lauten die entsprechenden Namespaceverweise Calc1AddInView.CalcAddInViews und Calc2Contract.CalculatorContracts, sofern der Standardnamespace für Visual Basic-Projekte nicht deaktiviert wurde.) Beachten Sie, dass der Namespace der Ansicht von Version 1 und der Vertrag von Version 2 stammt.

  8. Wenden Sie das AddInAdapterAttribute-Attribut auf die Calc2V1ViewToV2ContractAddInSideAdapter-Klasse an, um sie als den Add-In-seitigen Adapter zu definieren.

  9. Lassen Sie die Calc2V1ViewToV2ContractAddInSideAdapter-Klasse von ContractBase erben, um eine Standardimplementierung der IContract-Schnittstelle bereitzustellen, und implementieren Sie Version 2 der Vertragsschnittstelle für die Pipeline (ICalc2Contract).

  10. Fügen Sie einen öffentlichen Konstruktor hinzu, der einen ICalculator akzeptiert, diesen in einem privaten Feld zwischenspeichert und den Basisklassenkonstruktor aufruft.

  11. Um die Member von ICalc2Contract zu implementieren, müssen Sie die entsprechenden Member der ICalculator-Instanz aufrufen, die dem Konstruktor übergeben wird, und die Ergebnisse zurückgeben. Aufgrund der Unterschiede zwischen Version 1 und Version 2 der Vertragsschnittstellen benötigen Sie eine switch-Anweisung (Select Case-Anweisung in Visual Basic), um die Ansicht (ICalculator) an den Vertrag (ICalc2Contract) anzupassen.

    Im folgenden Code wird der vollständige Add-In-seitige Adapter dargestellt.

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

Erstellen des hostseitigen Adapters

Dieser hostseitige Adapter besteht aus einem Vertrag-zu-Ansicht-Adapter. Ein Vertrag-zu-Ansicht-Adapter ist für die Unterstützung beider Versionen des Add-Ins ausreichend, da jeder Add-In-seitige Adapter von seiner jeweiligen Ansicht zu Version 2 des Vertrags konvertiert.

In dieser Pipeline stellt das Add-In einen Dienst für den Host bereit, und die Typen fließen vom Add-In zum Host. Da keine Typen vom Host zum Add-In fließen, müssen Sie keinen Vertrag-zu-Ansicht-Adapter aufnehmen.

Zum Implementieren der Verwaltung der Lebensdauer verwenden Sie ein ContractHandle-Objekt, um ein Lebensdauertoken an den Vertrag anzufügen. Sie müssen einen Verweis auf dieses Handle verwenden, damit die Verwaltung der Lebensdauer funktioniert. Nach Anwendung des Tokens ist keine zusätzliche Programmierung erforderlich, da das Add-In-System Objekte entfernen kann, die nicht mehr verwendet werden, und diese Objekte für die Garbage Collection verfügbar macht. Weitere Informationen finden Sie unter Verwaltung der Lebensdauer.

So erstellen Sie den hostseitigen Adapter

  1. Fügen Sie der CalculatorV2-Projektmappe ein neues Projekt mit dem Namen Calc2HostInSideAdapter hinzu. Verwenden Sie die Klassenbibliothek-Vorlage als Grundlage.

  2. Fügen Sie im Projektmappen-Explorer dem Calc2HostSideAdapter-Projekt Verweise auf die folgenden Assemblys hinzu:

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Fügen Sie den folgenden Projekten Projektverweise hinzu:

    Calc2Contract

    Calc2HVA

  4. Wählen Sie die einzelnen Projektverweise aus, und legen Sie unter Eigenschaften die Option Lokale Kopie auf False fest, damit die Assemblys, auf die verwiesen wird, nicht in den lokalen Buildordner kopiert werden. In Visual Basic kann unter Projekteigenschaften auf der Registerkarte Verweise die Option Lokale Kopie auf False festgelegt werden.

  5. Benennen Sie die Standardklasse des Projekts in CalculatorContractToViewHostSideAdapter um.

  6. Fügen Sie in der Klassendatei Namespaceverweise auf System.AddIn.Pipeline hinzu.

  7. Fügen Sie in der Klassendatei Namespaceverweise für die benachbarten Segmente hinzu: CalcHVAs und CalculatorContracts. (In Visual Basic lauten die entsprechenden Namespaceverweise Calc2HVA.CalcHVAs und Calc2Contract.CalculatorContracts, sofern der Standardnamespace für Visual Basic-Projekte nicht deaktiviert wurde.)

  8. Wenden Sie das HostAdapterAttribute-Attribut auf die CalculatorContractToViewHostSideAdapter-Klasse an, um es als hostseitigen Adapter zu identifizieren.

  9. Lassen Sie die CalculatorContractToViewHostSideAdapter-Klasse von der abstrakten Basisklasse erben, die die Host-Ansicht des Add-Ins darstellt: CalcHVAs.Calculator (Calc2HVA.CalcHVAs.Calculator in Visual Basic). Beachten Sie den Unterschied zu Version 1, in der die Hostansicht des Add-Ins eine Schnittstelle ist.

  10. Fügen Sie einen öffentlichen Konstruktor hinzu, der den Pipelinevertragstyp ICalc2Contract akzeptiert. Der Konstruktor muss den Verweis auf den Vertrag zwischenspeichern. Der Konstruktor muss außerdem einen neuen ContractHandle für den Vertrag erstellen und zwischenspeichern, um die Lebensdauer des Add-Ins zu verwalten.

    Wichtiger Hinweis:

    Das ContractHandle ist für die Lebensdauerverwaltung entscheidend. Wenn Sie keinen Verweis auf das ContractHandle-Objekt beibehalten, wird es von der Garbage Collection freigegeben, und die Pipeline wird zu einem für das Programm unerwarteten Zeitpunkt beendet. Dies kann zu Fehlern führen, die schwierig zu diagnostizieren sind, z. B. AppDomainUnloadedException. Das Herunterfahren ist eine normale Phase im Lebenszyklus einer Pipeline, es gibt daher keine Möglichkeit für den Code zum Verwalten des Lebenszyklus festzustellen, dass es sich bei dem Zustand um einen Fehler handelt.

  11. Wenn Sie die Member von Calculator überschreiben möchten, rufen Sie einfach die entsprechenden Member der ICalc2Contract-Instanz auf, die dem Konstruktor übergeben wird, und geben die Ergebnisse zurück. Dadurch wird der Vertrag (ICalc2Contract) an die Ansicht (Calculator) angepasst.

    Im folgenden Code wird das vervollständigte hostseitige Adaptersegment dargestellt.

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

Erstellen des Hosts

Eine Hostanwendung interagiert durch die Hostansicht mit dem Add-In. Sie verwendet Methoden zur Add-In-Erkennung und -Aktivierung, die durch die AddInStore-Klasse und die AddInToken-Klasse bereitgestellt werden, um folgende Aktionen auszuführen:

  • Neuerstellen des Caches der Pipeline- und Add-In-Informationen.

  • Suchen von Add-Ins vom Typ Calculator unter dem angegebenen Pipelinestammverzeichnis.

  • Auffordern des Benutzers zur Angabe, welches Add-In verwendet werden soll. In diesem Beispiel sehen Sie zwei verfügbare Add-Ins.

  • Aktivieren des ausgewählten Add-Ins mit einer angegebenen Sicherheitsvertrauensebene in einer neuen Anwendungsdomäne.

  • Ausführen der RunCalculator-Methode, die die Methoden des Add-Ins gemäß den Angaben in der Hostansicht des Add-Ins aufruft.

So erstellen Sie den Host

  1. Fügen Sie der CalculatorV2-Projektmappe ein neues Projekt mit dem Namen MathHost2 hinzu. Verwenden Sie die Konsolenanwendungsvorlage als Grundlage.

  2. Fügen Sie im Projektmappen-Explorer dem MathHost2-Projekt einen Verweis auf die System.AddIn.dll-Assembly hinzu.

  3. Fügen Sie dem Calc2HVA-Projekt einen Projektverweis hinzu. Wählen Sie den Projektverweis aus, und legen Sie unter Eigenschaften die Option Lokale Kopie auf False fest, damit die Assembly, auf die verwiesen wird, nicht in den lokalen Buildordner kopiert wird. In Visual Basic kann unter Projekteigenschaften auf der Registerkarte Verweise die Option Lokale Kopie auf False festgelegt werden.

  4. Benennen Sie die Klassendatei (Modul in Visual Basic) in MathHost2 um.

  5. Verwenden Sie in Visual Basic im Dialogfeld Projekteigenschaften die Registerkarte Anwendung, um das Startobjekt auf Sub Main festzulegen.

  6. Fügen Sie in der Klassen- oder Moduldatei einen Namespaceverweis auf System.AddIn.Hosting hinzu.

  7. Fügen Sie in der Klassen- oder Moduldatei den Namespaceverweis CalcHVAs für die Hostansicht des Add-Ins hinzu. (In Visual Basic lautet der entsprechende Namespaceverweis Calc2HVA.CalcHVAs, sofern der Standardnamespace für Visual Basic-Projekte nicht deaktiviert wurde.)

  8. Wählen Sie die Projektmappe im Projektmappen-Explorer aus, und wählen Sie Eigenschaften aus dem Menü Projekt. Legen Sie im Dialogfeld Projektmappen-Eigenschaftenseiten die Option Einzelnes Startprojekt als Hostanwendungsprojekt fest.

  9. Erstellen Sie mit dem folgenden Code die Hostanwendung.

    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; }
            }
        }
    }
    
    Hinweis:

    Bei diesem Codebeispiel wird davon ausgegangen, dass sich die Pipelineordnerstruktur im Anwendungsordner befindet. Wenn sie sich an einem anderen Speicherort befindet, ändern Sie die Codezeile, mit der die addInRoot-Variable festgelegt wird, damit die Variable den Pfad zur Pipelineverzeichnisstruktur enthält.

Erstellen des Add-Ins

Ein Add-In implementiert die von der Add-In-Ansicht angegebenen Methoden. In diesem Add-In gibt die Operations-Methode eine Zeichenfolge mit einer Auflistung der mathematischen Operationen zurück, die das Add-In unterstützt. Die Operate-Methode stellt den Code zum Berechnen des Ergebnisses auf der Grundlage der Auswahl einer Operation und von zwei Zahlen durch den Host bereit.

So erstellen Sie das Add-In

  1. Fügen Sie der Projektmappe CalculatorV2 ein neues Projekt mit dem Namen AddInCalcV2 hinzu. Verwenden Sie die Klassenbibliothek-Vorlage als Grundlage.

  2. Fügen Sie im Projektmappen-Explorer dem Projekt AddInCalcV2 Verweise auf die folgenden Assemblys hinzu:

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. Fügen Sie dem Calc2AddInView-Projekt einen Projektverweis hinzu. Wählen Sie den Projektverweis aus, und legen Sie unter Eigenschaften die Option Lokale Kopie auf False fest, damit die Assembly, auf die verwiesen wird, nicht in den lokalen Buildordner kopiert wird. In Visual Basic kann unter Projekteigenschaften auf der Registerkarte Verweise die Option Lokale Kopie auf False festgelegt werden.

  4. Benennen Sie die Klassendatei in SampleV2AddIn um.

  5. Fügen Sie in der Klassendatei Namespaceverweise auf System.AddIn und auf System.AddIn.Pipeline hinzu. System.AddIn.Pipeline ist nur deshalb erforderlich, da der Code ein Beispiel für das QualificationDataAttribute-Attribut enthält.

  6. Fügen Sie in der Klassendatei einen Namespaceverweis für Version 2 des Add-In-Ansichtssegments hinzu: CalcAddInViews (Calc2AddInView.CalcAddInViews in Visual Basic).

  7. Wenden Sie das AddInAttribute-Attribut auf die SampleV2AddIn-Klasse an, um die Klasse als Add-In zu kennzeichnen.

  8. Wenden Sie das QualificationDataAttribute-Attribut auf die SampleV2AddIn-Klasse an, und geben Sie Informationen an, die der Host vom AddInToken abrufen kann. In diesem Fall enthalten die Informationen die Empfehlung, das Add-In in seine eigene Anwendungsdomäne zu laden. Siehe Gewusst wie: Verwenden von Qualifizierungsdaten.

  9. Lassen Sie die SampleV2AddIn-Klasse von der abstrakten Basisklasse Calculator2 erben, die die Add-In-Ansicht darstellt.

  10. Überschreiben Sie die Member von Calculator2, und geben Sie die Ergebnisse der entsprechenden Berechnungen zurück.

    Mit dem folgenden Code wird das vollständige Add-In dargestellt.

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

Bereitstellen der Pipeline

Sie können jetzt die Add-In-Segmente für die erforderliche Pipelineverzeichnisstruktur erstellen und bereitstellen.

So stellen Sie die Segmente in der Pipeline bereit

  1. Legen Sie für jedes Projekt der Projektmappe in den Projekteigenschaften auf der Registerkarte Build (der Registerkarte Kompilieren in Visual Basic) den Wert des Ausgabepfads (des Buildausgabepfads in Visual Basic) fest. Wenn Sie den Anwendungsordner beispielsweise MyApp genannt haben, werden Buildvorgänge der Projekte in den folgenden Ordnern durchgeführt:

    Projekt

    Pfad

    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

    Hinweis:

    Wenn für die Pipelineordnerstruktur ein anderer Speicherort als der Anwendungsordner verwendet wird, müssen die in der Tabelle angezeigten Pfade entsprechend angepasst werden.

  2. Erstellen Sie die Visual Studio-Projektmappe.

  3. Überprüfen Sie die Anwendungs- und Pipelineverzeichnisse, um sicherzustellen, dass die Assemblys in die richtigen Verzeichnisse kopiert und keine zusätzlichen Kopien der Assemblys in falschen Ordnern erstellt wurden.

    Hinweis:

    Wenn im AddInCalcV2-Projekt für den Calc2AddInView-Projektverweis die Option Lokale Kopie nicht auf False festgelegt wurde, kann das Add-In aufgrund von Kontextproblemen vom Ladeprogramm nicht gefunden werden.

    Informationen zum Bereitstellen in der Pipeline finden Sie unter Anforderungen für die Pipelineentwicklung.

Ausführen der Hostanwendung

Sie können jetzt den Host ausführen und mit den Add-Ins interagieren.

So führen Sie die Hostanwendung aus

  1. Stellen Sie sicher, dass beide Versionen des Add-Ins bereitgestellt wurden.

  2. Navigieren Sie an der Eingabeaufforderung zum Anwendungsverzeichnis, und führen Sie die Hostanwendung aus. In diesem Beispiel ist die Hostanwendung MathHost2.exe.

  3. Der Host sucht alle verfügbaren Add-Ins von seinem Typ und fordert Sie auf, ein Add-In auszuwählen. Geben Sie 1 oder 2 ein.

  4. Geben Sie eine Formel für den Rechner ein, z. B. 2 + 2.

  5. Geben Sie exit ein, und drücken Sie die EINGABETASTE, um die Anwendung zu schließen.

  6. Wiederholen Sie die Schritte 2 bis 5, um das andere Add-In auszuführen.

Siehe auch

Aufgaben

Exemplarische Vorgehensweise: Erstellen von erweiterbaren Anwendungen

Exemplarische Vorgehensweise: Übergeben von Auflistungen zwischen Hosts und Add-Ins

Konzepte

Anforderungen für die Pipelineentwicklung

Verträge, Ansichten und Adapter

Pipeline-Entwicklung

Änderungsprotokoll

Date

Versionsgeschichte

Grund

Juli 2008

Fehler im Text korrigiert. Hinweis zum Beibehalten eines Verweises auf den Vertrag hinzugefügt.

Kundenfeedback.