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

Diese exemplarische Vorgehensweise erläutert, wie eine Pipeline erstellt wird, die eine Auflistung angepasster Objekte zwischen dem Add-In und einem Host übergibt. Da die Typen in der Auflistung nicht serialisierbar sind, müssen den Adaptersegmenten zusätzliche Klassen hinzugefügt werden, die Ansicht-zu-Vertrag-Adapter und Vertrag-zu-Ansicht-Adapter definieren, sodass der Fluss der Typen die Isolationsgrenze überschreiten kann.

In diesem Szenario aktualisiert das Add-In eine Auflistung der Buchobjekte für den Host. Jedes Buchobjekt enthält Methoden, die den Titel des Buchs, Herausgeber, Preis und andere Daten abrufen und festlegen.

Als Beispiel erstellt der Host eine Buchauflistung; das Add-In senkt den Preis für alle Computerbücher um 20 Prozent und entfernt alle Bücher mit Horrorgeschichten aus der Auflistung. Anschließend erstellt das Add-In ein neues Buchobjekt für den Bestseller und übergibt dieses als einzelnes Objekt an den Host.

In dieser exemplarischen Vorgehensweise werden die folgenden Aufgaben veranschaulicht:

  • Erstellen einer Visual Studio-Projektmappe

  • Erstellen der Pipelineverzeichnisstruktur

  • Erstellen von Verträgen und Ansichten für Objekte, die über die Isolationsgrenze hinweg übergeben werden müssen.

  • Erstellen der Add-in-seitigen und hostseitigen Adapter, die für die Übergabe von Objekten über die Isolationsgrenze hinweg erforderlich sind.

  • Erstellen des Hosts

  • Erstellen des Add-Ins

  • Bereitstellen der Pipeline

  • Ausführen der Hostanwendung

HinweisHinweis

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 LibraryContracts. Verwenden Sie die Klassenbibliothek-Vorlage als Grundlage.

  2. Geben Sie der Projektmappe den Namen BooksPipeline.

Erstellen der Pipelineverzeichnisstruktur

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

So erstellen Sie die Pipelineverzeichnisstruktur

  • Erstellen Sie die folgende Ordnerstruktur auf dem Computer. Sie können die Ordnerstruktur an einem beliebigen Ort anlegen, auch innerhalb der Ordner der Visual Studio-Projektmappe.

    Pipeline
      AddIns
        BooksAddIn
      AddInSideAdapters
      AddInViews
      Contracts
      HostSideAdapters
    

    Alle Ordnernamen müssen genauso angegeben werden wie hier dargestellt, mit Ausnahme des Stammordnernamens und der Namen der einzelnen Add-In-Ordner. In diesem Beispiel wird Pipeline als Stammordnername und BooksAddIn als Name des Add-In-Ordners verwendet.

    HinweisHinweis

    Der Einfachheit halber befindet sich in dieser exemplarischen Vorgehensweise die Hostanwendung im Pipelinestammordner.Zu gegebener Zeit wird in dieser exemplarischen Vorgehensweise erläutert, wie der Code geändert werden muss, wenn sich die Anwendung an einem anderen Speicherort befindet.

    Weitere Informationen über die Pipelineordnerstruktur finden Sie unter Anforderungen für die Pipelineentwicklung.

Erstellen des Vertrags und der Ansichten

Das Vertragssegment für diese Pipeline definiert zwei Schnittstellen:

  • Die IBookInfoContract-Schnittstelle

    Diese Schnittstelle enthält die Methoden, z. B. Author, die Informationen über ein Buch enthalten.

  • Die ILibraryManagerContract-Schnittstelle

    Diese Schnittstelle enthält die ProcessBooks-Methode, die das Add-In verwendet, um eine Auflistung von Büchern zu verarbeiten. Jedes Buch stellt einen IBookInfoContract-Vertrag dar. Die Schnittstelle enthält auch die GetBestSeller-Methode, die das Add-In verwendet, um ein Buchobjekt (den Bestseller) für den Host bereitzustellen.

So erstellen Sie den Vertrag

  1. Öffnen Sie in der Visual Studio-Projektmappe BooksPipeline das LibraryContracts-Projekt.

  2. Öffnen Sie in Visual Basic das Dialogfeld Eigenschaften für das Projekt LibraryContracts, und löschen Sie mithilfe der Registerkarte Anwendung den Standardwert für Stammnamespace. Standardmäßig wird Stammnamespace auf den Projektnamen festgelegt.

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

    System.AddIn.Contract.dll

    System.AddIn.dll

  4. Fügen Sie in der Klassendatei Verweise auf den System.AddIn.Contract-Namespace und den System.AddIn.Pipeline-Namespace hinzu.

  5. Ersetzen Sie in der Klassendatei die Standardklassendeklaration durch zwei Schnittstellen:

    • Mit der ILibraryManagerContract-Schnittstelle wird das Add-In aktiviert. Aus diesem Grund muss es über das AddInContractAttribute-Attribut verfügen.

    • Die IBookInfoContract-Schnittstelle stellt ein Objekt dar, das zwischen dem Host und dem Add-In übergeben wird. Aus diesem Grund ist kein Attribut erforderlich.

    Beide Schnittstellen müssen die IContract-Schnittstelle erben.

  6. Fügen Sie mit dem folgenden Code die IBookInfoContract -Schnittstelle und die ILibraryManagerContract-Schnittstelle hinzu:

    
    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.AddIn.Pipeline
    Imports System.AddIn.Contract
    Namespace Library
    <AddInContract> _
    Public Interface ILibraryManagerContract
    Inherits IContract
        ' Pass a collection of books,
        ' of type IBookInfoContract
        ' to the add-in for processing.
        Sub ProcessBooks(ByVal books As IListContract(Of IBookInfoContract))
    
        ' Get a IBookInfoContract object
        ' from the add-in of the
        ' the best selling book.
        Function GetBestSeller() As IBookInfoContract
    
        ' This method has has arbitrary
        ' uses and shows how you can
        ' mix serializable and custom types.
        Function Data(ByVal txt As String) As String
    End Interface
    
    ' Contains infomration about a book.
    Public Interface IBookInfoContract
    Inherits IContract
        Function ID() As String
        Function Author() As String
        Function Title() As String
        Function Genre() As String
        Function Price() As String
        Function Publish_Date() As String
        Function Description() As String
    End Interface
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.AddIn.Pipeline;
    using System.AddIn.Contract;
    namespace Library
    {
        [AddInContract]
        public interface ILibraryManagerContract : IContract
        {
            // Pass a collection of books,
            // of type IBookInfoContract
            // to the add-in for processing.
            void ProcessBooks(IListContract<IBookInfoContract> books);
    
            // Get a IBookInfoContract object
            // from the add-in of the
            // the best selling book.
            IBookInfoContract GetBestSeller();
    
            // This method has has arbitrary
            // uses and shows how you can
            // mix serializable and custom types.
            string Data(string txt);
        }
    
        // Contains infomration about a book.
        public interface IBookInfoContract : IContract
        {
            string ID();
            string Author();
            string Title();
            string Genre();
            string Price();
            string Publish_Date();
            string Description();
        }
    }
    

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 nur in einer Hinsicht: Die Add-In-Ansicht mit der dieses Segment der Pipeline aktiviert wird, erfordert das AddInBaseAttribute-Attribut, während für die Hostansicht keine Attribute erforderlich sind.

Die Add-In-Ansicht für diese Pipeline enthält zwei abstrakte Klassen. Die BookInfo-Klasse stellt die Ansicht für die IBookInfoContract-Schnittstelle bereit. Die LibraryManager-Klasse stellt die Ansicht für die ILibraryManagerContract-Schnittstelle bereit.

So erstellen Sie die Add-In-Ansicht

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

  2. Öffnen Sie in Visual Basic das Dialogfeld Eigenschaften für das Projekt, und löschen Sie mithilfe der Registerkarte Anwendung den Standardwert für Stammnamespace.

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

  4. Benennen Sie die Standardklasse des Projekts in LibraryManager um, und legen Sie die Klasse als abstract (MustInherit in Visual Basic) fest.

  5. Fügen Sie in der Klassendatei einen Verweis auf den System.AddIn.Pipeline-Namespace hinzu.

  6. Mit der LibraryManager-Klasse wird die Pipeline aktiviert. Aus diesem Grund muss das AddInBaseAttribute-Attribut übernommen werden.

  7. Mit folgendem Code können Sie die abstrakte LibraryManager-Klasse vervollständigen.

    
    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    Imports System.AddIn.Pipeline
    Namespace LibraryContractsBase
    ' The AddInBaseAttribute
    ' identifes this pipeline
    ' segment as an add-in view.
    <AddInBase> _
    Public MustInherit Class LibraryManager
        Public MustOverride Sub ProcessBooks(ByVal books As IList(Of BookInfo))
        Public MustOverride Function GetBestSeller() As BookInfo
    
        Public MustOverride Function Data(ByVal txt As String) As String
    End Class
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.AddIn.Pipeline;
    namespace LibraryContractsBase
    {
    // The AddInBaseAttribute
    // identifes this pipeline
    // segment as an add-in view.
    [AddInBase]
        public abstract class LibraryManager
        {
            public abstract void ProcessBooks(IList<BookInfo> books);
            public abstract BookInfo GetBestSeller();
    
            public abstract string Data(string txt);
        }
    }
    
  8. Fügen Sie dem Projekt eine abstract-Klasse (MustInherit-Klasse in Visual Basic) hinzu, und geben Sie dieser den Namen BookInfo. Die BookInfo-Klasse stellt ein Objekt dar, das zwischen dem Host und dem Add-In übergeben wird. Diese Klasse wird nicht verwendet, um die Pipeline zu aktivieren. Aus diesem Grund erfordert sie keine Attribute.

  9. Mit folgendem Code können Sie die abstrakte BookInfo-Klasse vervollständigen.

    
    Imports Microsoft.VisualBasic
    Imports System
    Namespace LibraryContractsBase
    
    Public MustInherit Class BookInfo
    
        Public MustOverride Function ID() As String
        Public MustOverride Function Author() As String
        Public MustOverride Function Title() As String
        Public MustOverride Function Genre() As String
        Public MustOverride Function Price() As String
        Public MustOverride Function Publish_Date() As String
        Public MustOverride Function Description() As String
    End Class
    End Namespace
    
    using System;
    namespace LibraryContractsBase {
    
        public abstract class BookInfo {
    
            public abstract string ID();
            public abstract string Author();
            public abstract string Title();
            public abstract string Genre();
            public abstract string Price();
            public abstract string Publish_Date();
            public abstract string Description();
        }
    }
    

So erstellen Sie die Hostansicht

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

  2. Öffnen Sie in Visual Basic das Dialogfeld Eigenschaften für das Projekt, und löschen Sie mithilfe der Registerkarte Anwendung den Standardwert für Stammnamespace.

  3. Benennen Sie die Standardklasse des Projekts in LibraryManager um, und legen Sie die Klasse als abstract (MustInherit in Visual Basic) fest.

  4. Mit folgendem Code können Sie die abstrakte LibraryManager-Klasse vervollständigen.

    
    Imports Microsoft.VisualBasic
    Imports System.Collections.Generic
    Namespace LibraryContractsHAV
    
    Public MustInherit Class LibraryManager
    
    Public MustOverride Sub ProcessBooks(ByVal books As System.Collections.Generic.IList(Of BookInfo))
    Public MustOverride Function GetBestSeller() As BookInfo
    
    Public MustOverride Function Data(ByVal txt As String) As String
    End Class
    End Namespace
    
    using System.Collections.Generic;
    namespace LibraryContractsHAV {
    
    public abstract class LibraryManager
    {
    
        public abstract void ProcessBooks(System.Collections.Generic.IList<BookInfo> books);
        public abstract BookInfo GetBestSeller();
    
        public abstract string Data(string txt);
    }
    }
    
  5. Fügen Sie dem Projekt eine abstract-Klasse (MustInherit-Klasse in Visual Basic) hinzu, und geben Sie dieser den Namen BookInfo.

  6. Verwenden Sie den folgenden Code, um die abstrakte BookInfo-Klasse zu vervollständigen.

    
    Imports Microsoft.VisualBasic
    Imports System
    Namespace LibraryContractsHAV
        Public MustInherit Class BookInfo
    
            Public MustOverride Function ID() As String
            Public MustOverride Function Author() As String
            Public MustOverride Function Title() As String
            Public MustOverride Function Genre() As String
            Public MustOverride Function Price() As String
            Public MustOverride Function Publish_Date() As String
            Public MustOverride Function Description() As String
        End Class
    End Namespace
    
    namespace LibraryContractsHAV
    {
        public abstract class BookInfo
        {
    
            public abstract string ID();
            public abstract string Author();
            public abstract string Title();
            public abstract string Genre();
            public abstract string Price();
            public abstract string Publish_Date();
            public abstract string Description();
        }
    }
    

Erstellen des Add-In-seitigen Adapters

Die Add-In-seitige Adapterassembly für diese Pipeline enthält vier Adapterklassen:

  • BookInfoContractToViewAddInAdapter

    Dieser Adapter wird aufgerufen, wenn der Host ein BookInfo-Objekt einzeln oder als Teil einer Auflistung an das Add-In übergibt. Diese Klasse konvertiert den Vertrag des BookInfo-Objekts in eine Ansicht. Diese Klasse erbt von der Add-In-Ansicht und implementiert die abstrakten Methoden der Ansicht durch Aufrufen des Vertrags, der vom Konstruktor der Klasse übergeben wird.

    Der Konstruktor verwendet für diesen Adapter einen Vertrag. Dadurch kann ein ContractHandle-Objekt auf den Vertrag angewendet werden, um die Lebensdauerverwaltung zu implementieren.

    Wichtiger HinweisWichtig

    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.

  • BookInfoViewToContractAddInAdapter

    Dieser Adapter wird aufgerufen, wenn das Add-In ein BookInfo-Objekt an den Host übergibt. Diese Klasse konvertiert die Add-In-Ansicht des BookInfo-Objekts in einen Vertrag. Die Klasse erbt vom Vertrag und implementiert den Vertrag durch Aufrufen der Add-In-Ansicht, die an den Konstruktor der Klasse übergeben wird. Dieser Adapter wird zum Host als Vertrag gemarshallt.

  • LibraryManagerViewToContractAddInAdapter

    Dies ist der Typ, der an den Host von seinem Aufruf zum Aktivieren des Add-Ins zurückgegeben wird. Dieser Typ wird aufgerufen, wenn der Host das Add-In aufruft, einschließlich des Aufrufs, der eine Auflistung von Hostobjekten (IList<BookInfo>) an das Add-In übergibt. Diese Klasse konvertiert den ILibraryManagerContract-Vertrag in die LibraryManager-Hostansicht. Diese Klasse erbt von der Hostansicht und implementiert den Vertrag durch Aufrufen der Ansicht, die an ihren Konstruktor übergeben wird.

    Da eine Auflistung angepasster Typen, die BookInfo-Objekte, über die Isolationsgrenze gemarshallt werden muss, verwendet dieser Adapter die CollectionAdapters-Klasse. Diese Klasse stellt Methoden zum Umwandeln einer IList<T>-Auflistung in eine IListContract<T>-Auflistung bereit. Dadurch kann die Auflistung über die Isolationsgrenze hinweg auf die andere Seite der Pipeline übergeben werden.

  • BookInfoAddInAdapter

    Die static-Methoden (die Shared-Methoden in Visual Basic) dieses Adapters werden von der LibraryManagerViewToContractAddInAdapter-Klasse zum Anpassen eines Vertrags bzw. einer Ansicht aufgerufen oder um einen bestehenden Vertrag bzw. eine bestehende Ansicht zurückzugeben. Dies verhindert, dass ein zusätzlicher Adapter erstellt wird, wenn ein Objekt einen Roundtrip zwischen Host und Add-In durchläuft.

So erstellen Sie den Add-In-seitigen Adapter

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

  2. Öffnen Sie in Visual Basic das Dialogfeld Eigenschaften für das Projekt, und löschen Sie mithilfe der Registerkarte Anwendung den Standardwert für Stammnamespace.

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

    System.AddIn.dll

    System.AddIn.Contract.dll

  4. Fügen Sie im Projektmappen-Explorer dem AddInSideAdapters-Projekt Verweise auf die folgenden Projekte hinzu:

    AddInViews

    LibraryContracts

    Legen Sie unter Eigenschaften die Option Lokale Kopie für die Verweise 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, in der Pipelineverzeichnisstruktur.

  5. Nennen Sie die Klassendatei BookInfoContractToViewAddInAdapter.

  6. Fügen Sie in der Klassendatei einen Verweis auf den System.AddIn.Pipeline-Namespace hinzu.

  7. Fügen Sie mit dem folgenden Code die BookInfoContractToViewAddInAdapter-Klasse hinzu. Die Klasse benötigt kein Attribut, da sie nicht zum Aktivieren der Pipeline verwendet wird. Die internal (Friend in Visual Basic) GetSourceContract-Methode wird von der BookInfoAddInAdapter-Klasse verwendet, um zu verhindern, dass ein weiterer Adapter erstellt wird, wenn ein Objekt zwischen dem Host und dem Add-In einen Roundtrip durchläuft.

    
    Imports Microsoft.VisualBasic
    Imports System
    Imports System.AddIn.Pipeline
    Namespace LibraryContractsAddInAdapters
    
    Public Class BookInfoContractToViewAddInAdapter
        Inherits LibraryContractsBase.BookInfo
        Private _contract As Library.IBookInfoContract
        Private _handle As System.AddIn.Pipeline.ContractHandle
        Public Sub New(ByVal contract As Library.IBookInfoContract)
            _contract = contract
            _handle = New ContractHandle(contract)
        End Sub
    
        Public Overrides Function ID() As String
            Return _contract.ID()
        End Function
        Public Overrides Function Author() As String
            Return _contract.Author()
        End Function
        Public Overrides Function Title() As String
            Return _contract.Title()
        End Function
        Public Overrides Function Genre() As String
            Return _contract.Genre()
        End Function
        Public Overrides Function Price() As String
            Return _contract.Price()
        End Function
        Public Overrides Function Publish_Date() As String
            Return _contract.Publish_Date()
        End Function
        Public Overrides Function Description() As String
            Return _contract.Description()
        End Function
    
        Friend Function GetSourceContract() As Library.IBookInfoContract
            Return _contract
        End Function
    End Class
    End Namespace
    
    using System;
    using System.AddIn.Pipeline;
    namespace LibraryContractsAddInAdapters 
    {
    
    public class BookInfoContractToViewAddInAdapter : LibraryContractsBase.BookInfo 
    {
        private Library.IBookInfoContract _contract;
        private System.AddIn.Pipeline.ContractHandle _handle;
        public BookInfoContractToViewAddInAdapter(Library.IBookInfoContract contract) 
        {
            _contract = contract;
            _handle = new ContractHandle(contract);
        }
    
        public override string ID()
        {
            return _contract.ID();
        }
        public override string Author()
        {
            return _contract.Author();
        }
        public override string Title()
        {
            return _contract.Title();
        }
        public override string Genre()
        {
            return _contract.Genre();
        }
        public override string Price()
        {
            return _contract.Price();
        }
        public override string Publish_Date()
        {
            return _contract.Publish_Date();
        }
        public override string Description()
        {
            return _contract.Description();
        }
    
        internal Library.IBookInfoContract GetSourceContract() {
            return _contract;
        }
    }
    }
    
  8. Verwenden Sie den folgenden Code, um die BookInfoViewToContractAddInAdapter-Klasse dem AddInSideAdapters-Projekt hinzuzufügen. Die Klasse benötigt kein Attribut, da sie nicht zum Aktivieren der Pipeline verwendet wird. Die internal (Friend in Visual Basic) GetSourceView-Methode wird von der BookInfoAddInAdapter-Klasse verwendet, um zu verhindern, dass ein weiterer Adapter erstellt wird, wenn ein Objekt zwischen dem Host und dem Add-In einen Roundtrip durchläuft.

    
    Imports Microsoft.VisualBasic
    Imports System
    
    Namespace LibraryContractsAddInAdapters
    Public Class BookInfoViewToContractAddInAdapter
        Inherits System.AddIn.Pipeline.ContractBase
        Implements Library.IBookInfoContract
        Private _view As LibraryContractsBase.BookInfo
        Public Sub New(ByVal view As LibraryContractsBase.BookInfo)
            _view = view
        End Sub
        Public Overridable Function ID() As String Implements Library.IBookInfoContract.ID
            Return _view.ID()
        End Function
        Public Overridable Function Author() As String Implements Library.IBookInfoContract.Author
            Return _view.Author()
        End Function
        Public Overridable Function Title() As String Implements Library.IBookInfoContract.Title
            Return _view.Title()
        End Function
        Public Overridable Function Genre() As String Implements Library.IBookInfoContract.Genre
            Return _view.Genre()
        End Function
        Public Overridable Function Price() As String Implements Library.IBookInfoContract.Price
            Return _view.Price()
        End Function
        Public Overridable Function Publish_Date() As String Implements Library.IBookInfoContract.Publish_Date
            Return _view.Publish_Date()
        End Function
        Public Overridable Function Description() As String Implements Library.IBookInfoContract.Description
            Return _view.Description()
        End Function
    
        Friend Function GetSourceView() As LibraryContractsBase.BookInfo
            Return _view
        End Function
    End Class
    End Namespace
    
    using System;
    
    namespace LibraryContractsAddInAdapters 
    {
    public class BookInfoViewToContractAddInAdapter : System.AddIn.Pipeline.ContractBase, Library.IBookInfoContract 
    {
        private LibraryContractsBase.BookInfo _view;
        public BookInfoViewToContractAddInAdapter(LibraryContractsBase.BookInfo view) 
        {
            _view = view;
        }
        public virtual string ID()
        {
            return _view.ID();
        }
        public virtual string Author()
        {
            return _view.Author();
        }
        public virtual string Title()
        {
            return _view.Title();
        }
        public virtual string Genre()
        {
            return _view.Genre();
        }
        public virtual string Price()
        {
            return _view.Price();
        }
        public virtual string Publish_Date()
        {
            return _view.Publish_Date();
        }
        public virtual string Description()
        {
            return _view.Description();
        }
    
        internal LibraryContractsBase.BookInfo GetSourceView() {
            return _view;
        }
    }
    }
    
  9. Verwenden Sie den folgenden Code, um die LibraryManagerViewToContractAddInAdapter-Klasse dem AddInSideAdapters-Projekt hinzuzufügen. Diese Klasse benötigt das AddInAdapterAttribute-Attribut, da sie zum Aktivieren der Pipeline verwendet wird.

    Mit der ProcessBooks-Methode wird dargestellt, wie eine Liste von Büchern über die Isolationsgrenze hinweg übergeben wird. Sie verwendet die CollectionAdapters.ToIList-Methode, um die Liste zu konvertieren. Zum Konvertieren der Objekte in der Liste werden Delegaten für die von der BookInfoAddInAdapter-Klasse bereitgestellten Adaptermethoden übergeben.

    Mit der GetBestSeller-Methode wird dargestellt, wie ein einzelnes BookInfo-Objekt über die Isolationsgrenze hinweg übergeben wird.

    
    Imports Microsoft.VisualBasic
    Imports System.AddIn.Pipeline
    Imports System.AddIn.Contract
    Imports System.Collections.Generic
    Namespace LibraryContractsAddInAdapters
    ' The AddInAdapterAttribute
    ' identifes this pipeline
    ' segment as an add-in-side adapter.
    <AddInAdapter> _
    Public Class LibraryManagerViewToContractAddInAdapter
        Inherits System.AddIn.Pipeline.ContractBase
        Implements Library.ILibraryManagerContract
        Private _view As LibraryContractsBase.LibraryManager
        Public Sub New(ByVal view As LibraryContractsBase.LibraryManager)
            _view = view
        End Sub
        Public Overridable Sub ProcessBooks(ByVal books As IListContract(Of Library.IBookInfoContract)) Implements Library.ILibraryManagerContract.ProcessBooks
            _view.ProcessBooks(CollectionAdapters.ToIList(Of Library.IBookInfoContract, _
            LibraryContractsBase.BookInfo)(books, _
            AddressOf LibraryContractsAddInAdapters.BookInfoAddInAdapter.ContractToViewAdapter, _
            AddressOf LibraryContractsAddInAdapters.BookInfoAddInAdapter.ViewToContractAdapter))
        End Sub
        Public Overridable Function GetBestSeller() As Library.IBookInfoContract Implements Library.ILibraryManagerContract.GetBestSeller
            Return BookInfoAddInAdapter.ViewToContractAdapter(_view.GetBestSeller())
        End Function
    
        Public Overridable Function Data(ByVal txt As String) As String Implements Library.ILibraryManagerContract.Data
            Dim rtxt As String = _view.Data(txt)
            Return rtxt
        End Function
    
        Friend Function GetSourceView() As LibraryContractsBase.LibraryManager
            Return _view
        End Function
    End Class
    End Namespace
    
    using System.IO;
    using System.AddIn.Pipeline;
    using System.AddIn.Contract;
    using System.Collections.Generic;
    namespace LibraryContractsAddInAdapters
    {
    // The AddInAdapterAttribute
    // identifes this pipeline
    // segment as an add-in-side adapter.
    [AddInAdapter]
    public class LibraryManagerViewToContractAddInAdapter :
    System.AddIn.Pipeline.ContractBase, Library.ILibraryManagerContract
    {
        private LibraryContractsBase.LibraryManager _view;
        public LibraryManagerViewToContractAddInAdapter(LibraryContractsBase.LibraryManager view)
        {
            _view = view;
        }
        public virtual void ProcessBooks(IListContract<Library.IBookInfoContract> books)
        {
            _view.ProcessBooks(CollectionAdapters.ToIList<Library.IBookInfoContract,
                LibraryContractsBase.BookInfo>(books,
                LibraryContractsAddInAdapters.BookInfoAddInAdapter.ContractToViewAdapter,
                LibraryContractsAddInAdapters.BookInfoAddInAdapter.ViewToContractAdapter));
        }
        public virtual Library.IBookInfoContract GetBestSeller()
        {
            return BookInfoAddInAdapter.ViewToContractAdapter(_view.GetBestSeller());
        }
    
        public virtual string Data(string txt)
        {
            string rtxt = _view.Data(txt);
            return rtxt;
        }
    
        internal LibraryContractsBase.LibraryManager GetSourceView()
        {
            return _view;
        }
    }
    }
    
  10. Verwenden Sie den folgenden Code, um die BookInfoAddInAdapter-Klasse dem AddInSideAdapters-Projekt hinzuzufügen. Die Klasse enthält zwei static-Methoden (Shared-Methoden in Visual Basic): ContractToViewAdapter und ViewToContractAdapter. Die Methoden sind internal (Friend in Visual Basic), da sie nur von anderen Adapterklassen verwendet werden. Der Zweck dieser Methoden ist es, zu verhindern, dass ein zusätzlicher Adapter erstellt wird, wenn ein Objekt zwischen dem Host und dem Add-In (in einer der Richtungen) einen Roundtrip durchläuft. Diese Methoden sollten für Adapter bereitgestellt werden, die Objekte über die Isolationsgrenze hinweg übergeben.

    
    Imports Microsoft.VisualBasic
    Imports System
    Namespace LibraryContractsAddInAdapters
    
    Public Class BookInfoAddInAdapter
      Friend Shared Function ContractToViewAdapter(ByVal contract As Library.IBookInfoContract) As LibraryContractsBase.BookInfo
        If (Not System.Runtime.Remoting.RemotingServices.IsObjectOutOfAppDomain(contract)) AndAlso _
            CType(contract, Object).GetType().Equals(GetType(BookInfoViewToContractAddInAdapter)) Then
            Return (CType(contract, BookInfoViewToContractAddInAdapter)).GetSourceView()
        Else
            Return New BookInfoContractToViewAddInAdapter(contract)
        End If
    
      End Function
    
    Friend Shared Function ViewToContractAdapter(ByVal view As LibraryContractsBase.BookInfo) As Library.IBookInfoContract
        If (Not System.Runtime.Remoting.RemotingServices.IsObjectOutOfAppDomain(view)) AndAlso _
            view.GetType().Equals(GetType(BookInfoContractToViewAddInAdapter)) Then
            Return (CType(view, BookInfoContractToViewAddInAdapter)).GetSourceContract()
        Else
            Return New BookInfoViewToContractAddInAdapter(view)
        End If
    End Function
    End Class
    End Namespace
    
    using System;
    namespace LibraryContractsAddInAdapters {
    
    public class BookInfoAddInAdapter
    {
        internal static LibraryContractsBase.BookInfo ContractToViewAdapter(Library.IBookInfoContract contract)
        {
            if (!System.Runtime.Remoting.RemotingServices.IsObjectOutOfAppDomain(contract) &&
                (contract.GetType().Equals(typeof(BookInfoViewToContractAddInAdapter))))
            {
                return ((BookInfoViewToContractAddInAdapter)(contract)).GetSourceView();
            }
            else {
                return new BookInfoContractToViewAddInAdapter(contract);
            }
    
        }
    
        internal static Library.IBookInfoContract ViewToContractAdapter(LibraryContractsBase.BookInfo view)
        {
            if (!System.Runtime.Remoting.RemotingServices.IsObjectOutOfAppDomain(view) &&
                (view.GetType().Equals(typeof(BookInfoContractToViewAddInAdapter))))
            {
                return ((BookInfoContractToViewAddInAdapter)(view)).GetSourceContract();
            }
            else {
                return new BookInfoViewToContractAddInAdapter(view);
            }
        }
    }
    }
    

Erstellen des hostseitigen Adapters

Die hostseitige Adapterassembly für diese Pipeline enthält vier Adapterklassen:

  • BookInfoContractToViewHostAdapter

    Dieser Adapter wird aufgerufen, wenn das Add-In ein BookInfo-Objekt einzeln oder als Teil einer Auflistung an den Host übergibt. Diese Klasse konvertiert den Vertrag des BookInfo-Objekts in eine Ansicht. Diese Klasse erbt von der Hostansicht und implementiert die abstrakten Methoden der Ansicht durch Aufrufen des Vertrags, der vom Konstruktor der Klasse übergeben wird.

    Der Konstruktor verwendet für diesen Adapter einen Vertrag. Dadurch kann ein ContractHandle-Objekt auf den Vertrag angewendet werden, um die Lebensdauerverwaltung zu implementieren.

    Wichtiger HinweisWichtig

    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.

  • BookInfoViewToContractHostAdapter

    Dieser Adapter wird aufgerufen, wenn der Host ein BookInfo-Objekt an das Add-In übergibt. Diese Klasse konvertiert die Hostansicht des BookInfo-Objekts in einen Vertrag. Die Klasse erbt vom Vertrag und implementiert den Vertrag durch Aufrufen der Add-In-Ansicht, die an den Konstruktor der Klasse übergeben wird. Dieser Adapter wird zum Add-In als Vertrag gemarshallt.

  • LibraryManagerContractToViewHostAdapter

    Dieser Adapter wird aufgerufen, wenn der Host eine Auflistung von BookInfo-Objekten an das Add-In übergibt. Das Add-In führt seine Implementierung der ProcessBooks-Methode für diese Auflistung durch.

    Diese Klasse konvertiert die Hostansicht des LibraryManager-Objekts in einen Vertrag. Sie erbt vom Vertrag und implementiert den Vertrag durch Aufrufen der Hostansicht, die an den Konstruktor der Klasse übergeben wird.

    Da eine Auflistung angepasster Typen, die BookInfo-Objekte, über die Isolationsgrenze gemarshallt werden muss, verwendet dieser Adapter die CollectionAdapters-Klasse. Diese Klasse stellt Methoden zum Umwandeln einer IList<T>-Auflistung in eine IListContract<T>-Auflistung bereit. Dadurch kann die Auflistung über die Isolationsgrenze hinweg auf die andere Seite der Pipeline übergeben werden.

  • BookInfoHostAdapter

    Dieser Adapter wird von der LibraryManagerViewToContractHostAdapter-Klasse aufgerufen, um alle vorhandenen Verträge oder Ansichten für die Anpassung zurückzugeben anstatt neue Instanzen für den Aufruf zu erstellen. Dies verhindert, dass ein zusätzlicher Adapter erstellt wird, wenn ein Objekt zwischen Host und Add-In (in einer der Richtungen) einen Roundtrip durchläuft.

So erstellen Sie den hostseitigen Adapter

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

  2. Öffnen Sie in Visual Basic das Dialogfeld Eigenschaften für das Projekt, und löschen Sie mithilfe der Registerkarte Anwendung den Standardwert für Stammnamespace.

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

    System.AddIn.dll

    System.AddIn.Contract.dll

  4. Fügen Sie im Projektmappen-Explorer dem HostAdapters-Projekt Verweise auf die folgenden Projekte hinzu:

    HostViews

    LibraryContracts

    Legen Sie unter Eigenschaften die Option Lokale Kopie für die Verweise auf False fest, damit die Assemblys, auf die verwiesen wird, nicht in den lokalen Buildordner kopiert werden.

  5. Fügen Sie in der Klassendatei einen Verweis auf den System.AddIn.Pipeline-Namespace hinzu.

  6. Fügen Sie mit dem folgenden Code die BookInfoContractToViewHostAdapter-Klasse hinzu. Die Klasse benötigt kein Attribut, da sie nicht zum Aktivieren der Pipeline verwendet wird. Die internal (Friend in Visual Basic) GetSourceContract-Methode wird von der BookInfoAddInAdapter-Klasse verwendet, um zu verhindern, dass ein zusätzlicher Adapter erstellt wird, wenn ein Objekt zwischen dem Host und dem Add-In einen Roundtrip durchläuft.

    
    Imports Microsoft.VisualBasic
    Imports System.AddIn.Pipeline
    Namespace LibraryContractsHostAdapters
    Public Class BookInfoContractToViewHostAdapter
        Inherits LibraryContractsHAV.BookInfo
        Private _contract As Library.IBookInfoContract
    
        Private _handle As ContractHandle
    
        Public Sub New(ByVal contract As Library.IBookInfoContract)
            _contract = contract
            _handle = New ContractHandle(contract)
        End Sub
    
        Public Overrides Function ID() As String
            Return _contract.ID()
        End Function
        Public Overrides Function Author() As String
            Return _contract.Author()
        End Function
        Public Overrides Function Title() As String
            Return _contract.Title()
        End Function
        Public Overrides Function Genre() As String
            Return _contract.Genre()
        End Function
        Public Overrides Function Price() As String
            Return _contract.Price()
        End Function
        Public Overrides Function Publish_Date() As String
            Return _contract.Publish_Date()
        End Function
        Public Overrides Function Description() As String
            Return _contract.Description()
        End Function
    
    
        Friend Function GetSourceContract() As Library.IBookInfoContract
            Return _contract
        End Function
    End Class
    End Namespace
    
    using System.AddIn.Pipeline;
    namespace LibraryContractsHostAdapters
    {
        public class BookInfoContractToViewHostAdapter : LibraryContractsHAV.BookInfo
        {
            private Library.IBookInfoContract _contract;
    
            private ContractHandle _handle;
    
            public BookInfoContractToViewHostAdapter(Library.IBookInfoContract contract)
            {
                _contract = contract;
                _handle = new ContractHandle(contract);
            }
    
            public override string ID()
            {
                return _contract.ID();
            }
            public override string Author()
            {
                return _contract.Author();
            }
            public override string Title()
            {
                return _contract.Title();
            }
            public override string Genre()
            {
                return _contract.Genre();
            }
            public override string Price()
            {
                return _contract.Price();
            }
            public override string Publish_Date()
            {
                return _contract.Publish_Date();
            }
            public override string Description()
            {
                return _contract.Description();
            }
    
    
            internal Library.IBookInfoContract GetSourceContract() {
                return _contract;
            }
        }
    }
    
  7. Verwenden Sie den folgenden Code, um BookInfoViewToContractHostAdapter dem HostSideAdapters-Projekt hinzuzufügen. Die Klasse benötigt kein Attribut, da sie nicht zum Aktivieren der Pipeline verwendet wird. Die internal (Friend in Visual Basic) GetSourceView-Methode wird von der BookInfoAddInAdapter-Klasse verwendet, um zu verhindern, dass ein zusätzlicher Adapter erstellt wird, wenn ein Objekt zwischen dem Host und dem Add-In einen Roundtrip durchläuft.

    
    Imports Microsoft.VisualBasic
    Imports System.AddIn.Pipeline
    Namespace LibraryContractsHostAdapters
    Public Class BookInfoViewToContractHostAdapter
        Inherits ContractBase
        Implements Library.IBookInfoContract
        Private _view As LibraryContractsHAV.BookInfo
    
        Public Sub New(ByVal view As LibraryContractsHAV.BookInfo)
            _view = view
        End Sub
    
        Public Overridable Function ID() As String Implements Library.IBookInfoContract.ID
            Return _view.ID()
        End Function
        Public Overridable Function Author() As String Implements Library.IBookInfoContract.Author
            Return _view.Author()
        End Function
        Public Overridable Function Title() As String Implements Library.IBookInfoContract.Title
            Return _view.Title()
        End Function
        Public Overridable Function Genre() As String Implements Library.IBookInfoContract.Genre
            Return _view.Genre()
        End Function
        Public Overridable Function Price() As String Implements Library.IBookInfoContract.Price
            Return _view.Price()
        End Function
        Public Overridable Function Publish_Date() As String Implements Library.IBookInfoContract.Publish_Date
            Return _view.Publish_Date()
        End Function
        Public Overridable Function Description() As String Implements Library.IBookInfoContract.Description
            Return _view.Description()
        End Function
        Friend Function GetSourceView() As LibraryContractsHAV.BookInfo
            Return _view
        End Function
    End Class
    End Namespace
    
    using System.AddIn.Pipeline;
    namespace LibraryContractsHostAdapters
    {
    public class BookInfoViewToContractHostAdapter : ContractBase, Library.IBookInfoContract
    {
        private LibraryContractsHAV.BookInfo _view;
    
        public BookInfoViewToContractHostAdapter(LibraryContractsHAV.BookInfo view)
        {
            _view = view;
        }
    
        public virtual string ID()
        {
            return _view.ID();
        }
        public virtual string Author()
        {
            return _view.Author();
        }
        public virtual string Title()
        {
            return _view.Title();
        }
        public virtual string Genre()
        {
            return _view.Genre();
        }
        public virtual string Price()
        {
            return _view.Price();
        }
        public virtual string Publish_Date()
        {
            return _view.Publish_Date();
        }
        public virtual string Description()
        {
            return _view.Description();
        }
        internal LibraryContractsHAV.BookInfo GetSourceView()
        {
            return _view;
        }
    }
    }
    
  8. Verwenden Sie den folgenden Code, um LibraryManagerContractToViewHostAdapter dem HostSideAdapters-Projekt hinzuzufügen. Diese Klasse benötigt das HostAdapterAttribute-Attribut, da sie zum Aktivieren der Pipeline verwendet wird.

    Mit der ProcessBooks-Methode wird dargestellt, wie eine Liste von Büchern über die Isolationsgrenze hinweg übergeben wird. Sie verwendet die CollectionAdapters.ToIListContract-Methode, um die Liste zu konvertieren. Zum Konvertieren der Objekte in der Liste werden Delegaten für die von der BookInfoHostAdapter-Klasse bereitgestellten Adaptermethoden übergeben.

    Mit der GetBestSeller-Methode wird dargestellt, wie ein einzelnes BookInfo-Objekt über die Isolationsgrenze hinweg übergeben wird.

    
    Imports Microsoft.VisualBasic
    Imports System.Collections.Generic
    Imports System.AddIn.Pipeline
    Namespace LibraryContractsHostAdapters
        <HostAdapterAttribute()> _
        Public Class LibraryManagerContractToViewHostAdapter
            Inherits LibraryContractsHAV.LibraryManager
    
            Private _contract As Library.ILibraryManagerContract
            Private _handle As System.AddIn.Pipeline.ContractHandle
    
            Public Sub New(ByVal contract As Library.ILibraryManagerContract)
                _contract = contract
                _handle = New System.AddIn.Pipeline.ContractHandle(contract)
            End Sub
    
            Public Overrides Sub ProcessBooks(ByVal books As IList(Of LibraryContractsHAV.BookInfo))
                _contract.ProcessBooks(CollectionAdapters.ToIListContract(Of LibraryContractsHAV.BookInfo, _
                Library.IBookInfoContract)(books, _
                AddressOf LibraryContractsHostAdapters.BookInfoHostAdapter.ViewToContractAdapter, _
                AddressOf LibraryContractsHostAdapters.BookInfoHostAdapter.ContractToViewAdapter))
            End Sub
    
            Public Overrides Function GetBestSeller() As LibraryContractsHAV.BookInfo
                Return BookInfoHostAdapter.ContractToViewAdapter(_contract.GetBestSeller())
            End Function
    
            Friend Function GetSourceContract() As Library.ILibraryManagerContract
                Return _contract
            End Function
            Public Overrides Function Data(ByVal txt As String) As String
                Dim rtxt As String = _contract.Data(txt)
                Return rtxt
            End Function
        End Class
    End Namespace
    
    using System.Collections.Generic;
    using System.AddIn.Pipeline;
    namespace LibraryContractsHostAdapters
    {
    [HostAdapterAttribute()]
    public class LibraryManagerContractToViewHostAdapter : LibraryContractsHAV.LibraryManager
    {
    
        private Library.ILibraryManagerContract _contract;
        private System.AddIn.Pipeline.ContractHandle _handle;
    
        public LibraryManagerContractToViewHostAdapter(Library.ILibraryManagerContract contract)
        {
            _contract = contract;
            _handle = new System.AddIn.Pipeline.ContractHandle(contract);
        }
    
        public override void ProcessBooks(IList<LibraryContractsHAV.BookInfo> books) {
            _contract.ProcessBooks(CollectionAdapters.ToIListContract<LibraryContractsHAV.BookInfo,
                Library.IBookInfoContract>(books,
                LibraryContractsHostAdapters.BookInfoHostAdapter.ViewToContractAdapter,
                LibraryContractsHostAdapters.BookInfoHostAdapter.ContractToViewAdapter));
        }
    
        public override LibraryContractsHAV.BookInfo GetBestSeller()
        {
            return BookInfoHostAdapter.ContractToViewAdapter(_contract.GetBestSeller());
        }
    
        internal Library.ILibraryManagerContract GetSourceContract()
        {
            return _contract;
        }
        public override string Data(string txt)
        {
            string rtxt = _contract.Data(txt);
            return rtxt;
        }
    }
    }
    
  9. Verwenden Sie den folgenden Code, um die BookInfoHostAdapter-Klasse dem HostSideAdapters-Projekt hinzuzufügen. Die Klasse enthält zwei static-Methoden (Shared-Methoden in Visual Basic): ContractToViewAdapter und ViewToContractAdapter. Die Methoden sind internal (Friend in Visual Basic), da sie nur von anderen Adapterklassen verwendet werden. Der Zweck dieser Methoden ist es, zu verhindern, dass ein zusätzlicher Adapter erstellt wird, wenn ein Objekt zwischen dem Host und dem Add-In (in einer der Richtungen) einen Roundtrip durchläuft. Diese Methoden sollten für Adapter bereitgestellt werden, die Objekte über die Isolationsgrenze hinweg übergeben.

    
    Imports Microsoft.VisualBasic
    Imports System
    Namespace LibraryContractsHostAdapters
    Public Class BookInfoHostAdapter
    
    Friend Shared Function ContractToViewAdapter(ByVal contract As Library.IBookInfoContract) As LibraryContractsHAV.BookInfo
        If Not System.Runtime.Remoting.RemotingServices.IsObjectOutOfAppDomain(contract) AndAlso _
            CType(contract, Object).GetType().Equals(GetType(BookInfoViewToContractHostAdapter)) Then
            Return (CType(contract, BookInfoViewToContractHostAdapter)).GetSourceView()
        Else
            Return New BookInfoContractToViewHostAdapter(contract)
        End If
    End Function
    
    Friend Shared Function ViewToContractAdapter(ByVal view As LibraryContractsHAV.BookInfo) As Library.IBookInfoContract
        If Not System.Runtime.Remoting.RemotingServices.IsObjectOutOfAppDomain(view) AndAlso _
            view.GetType().Equals(GetType(BookInfoContractToViewHostAdapter)) Then
            Return (CType(view, BookInfoContractToViewHostAdapter)).GetSourceContract()
        Else
            Return New BookInfoViewToContractHostAdapter(view)
        End If
    End Function
    End Class
    End Namespace
    
    using System;
    namespace LibraryContractsHostAdapters
    {
    public class BookInfoHostAdapter
    {
    
        internal static LibraryContractsHAV.BookInfo ContractToViewAdapter(Library.IBookInfoContract contract)
        {
            if (!System.Runtime.Remoting.RemotingServices.IsObjectOutOfAppDomain(contract) &&
                (contract.GetType().Equals(typeof(BookInfoViewToContractHostAdapter))))
            {
                return ((BookInfoViewToContractHostAdapter)(contract)).GetSourceView();
    
            }
            else {
                return new BookInfoContractToViewHostAdapter(contract);
            }
        }
    
        internal static Library.IBookInfoContract ViewToContractAdapter(LibraryContractsHAV.BookInfo view)
        {
            if (!System.Runtime.Remoting.RemotingServices.IsObjectOutOfAppDomain(view) &&
                (view.GetType().Equals(typeof(BookInfoContractToViewHostAdapter))))
            {
                return ((BookInfoContractToViewHostAdapter)(view)).GetSourceContract();
            }
            else {
                return new BookInfoViewToContractHostAdapter(view);
            }
        }
    }
    }
    

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 LibraryManager unter dem angegebenen Pipelinestammverzeichnis.

  • Auffordern des Benutzers zum Auswählen der zu verwendenden Add-Ins In diesem Beispiel ist nur ein Add-In verfügbar.

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

  • Rufen Sie die ProcessBooks-Methode auf, um dem Add-In eine Auflistung von BookInfo-Objekten hinzuzufügen. Das Add-In ruft seine Implementierung der ProcessBooks-Methode auf und führt Funktionen aus, wie z. B. einen Preisnachlass von 20 Prozent auf Computerbücher.

  • Ruft die GetBestSeller -Methode auf, die das Add-In verwendet, um ein BookInfo-Objekt mit Informationen über den Bestseller zurückzugeben.

  • Ruft die Data-Methode auf, um den aktuellen Umsatzsteuersatz aus dem Add-In abzurufen. Diese Methode verwendet eine Zeichenfolge und gibt sie zurück, bei der es sich um einen versiegelten serialisierbaren Referenztyp handelt. Infolgedessen kann die Methode über die Isolationsgrenze an die andere Seite der Pipeline übertragen werden, ohne Ansicht-zu-Vertrag- oder Vertrag-zu-Ansicht-Adapter zu verwenden.

Der Host verfügt über eine CreateBooks-Methode, die eine Auflistung von BookInfo-Objekten erstellt. Diese Methode erstellt eine Auflistung mithilfe der unter Sample XML File (books.xml) verfügbaren Beispieldatei books.xml.

So erstellen Sie den Host

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

  2. Öffnen Sie in Visual Basic das Dialogfeld Eigenschaften für das Projekt, und löschen Sie mithilfe der Registerkarte Anwendung den Standardwert für Stammnamespace.

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

  4. Fügen Sie dem HostViews-Projekt einen Projektverweis hinzu. Legen Sie unter Eigenschaften die Option Lokale Kopie für diesen Verweis auf False fest, damit die Assembly, auf die verwiesen wird, nicht in den lokalen Buildordner kopiert wird.

  5. Wandeln Sie in Visual Basic das Modul in eine Klasse um:

    • Schließen Sie das Standardmodul vom Projekt aus, und fügen Sie dann eine Klasse mit dem Namen Program hinzu.

    • Ersetzen Sie das Public-Schlüsselwort durch das Friend-Schlüsselwort.

    • Fügen Sie der Klasse eine Shared Sub Main()-Prozedur hinzu.

    • In Visual Basic können Sie im Dialogfeld Projekteigenschaften auf der Registerkarte Anwendung das Startobjekt auf Sub Main festlegen.

  6. Fügen Sie in der Klassendatei Verweise auf System.AddIn.Pipeline und die Namespaces des Hostansichtssegments hinzu.

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

  8. Verwenden Sie den folgenden Code für die Hostanwendung.

    HinweisHinweis

    Ändern Sie im Code den Speicherort, von dem die Datei books.xml geladen wird in "books.xml", um die Datei aus dem Anwendungsordner zu laden.Wenn die Anwendung in einem anderen als dem Pipeline-Ordner gespeichert werden soll, muss die Codezeile, mit der die addInRoot-Variable festgelegt wird, so geändert werden, dass die Variable den Pfad zur Pipelineverzeichnisstruktur enthält.

    
    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    Imports System.Collections.ObjectModel
    Imports System.Text
    Imports LibraryContractsHAV
    Imports System.AddIn.Hosting
    Imports System.Xml
    
    
    Namespace ListAdaptersHost
    Friend Class Program
    Shared Sub Main(ByVal args As String())
    
        ' In this example, the pipeline root is the current directory.
        Dim pipeRoot As String = Environment.CurrentDirectory
    
        ' Rebuild the cache of pipeline and add-in information.
        Dim warnings As String() = AddInStore.Update(pipeRoot)
        If warnings.Length > 0 Then
            For Each one As String In warnings
                Console.WriteLine(one)
            Next one
        End If
    
        ' Find add-ins of type LibraryManager under the specified pipeline root directory.
        Dim tokens As Collection(Of AddInToken) = AddInStore.FindAddIns(GetType(LibraryManager), pipeRoot)
        ' Determine which add-in to use.
        Dim selectedToken As AddInToken = ChooseAddIn(tokens)
    
        ' Activate the selected AddInToken in a new
        ' application domain with a specified security trust level.
        Dim manager As LibraryManager = selectedToken.Activate(Of LibraryManager)(AddInSecurityLevel.FullTrust)
    
        ' Create a collection of books.
        Dim books As IList(Of BookInfo) = CreateBooks()
    
        ' Show the collection count.
        Console.WriteLine("Number of books:  {0}",books.Count.ToString())
    
        ' Have the add-in process the books.
        ' The add-in will discount computer books by $20
        ' and list their before and after prices. It
        ' will also remove all horror books.
        manager.ProcessBooks(books)
    
        ' List the genre of each book. There
        ' should be no horror books.
        For Each bk As BookInfo In books
            Console.WriteLine(bk.Genre())
        Next bk
    
        Console.WriteLine("Number of books: {0}", books.Count.ToString())
    
        Console.WriteLine()
        ' Have the add-in pass a BookInfo object
        ' of the best selling book.
        Dim bestBook As BookInfo = manager.GetBestSeller()
        Console.WriteLine("Best seller is {0} by {1}", bestBook.Title(), bestBook.Author())
    
        ' Have the add-in show the sales tax rate.
        manager.Data("sales tax")
    
        Dim ctrl As AddInController = AddInController.GetAddInController(manager)
        ctrl.Shutdown()
        Console.WriteLine("Press any key to exit.")
        Console.ReadLine()
    End Sub
    
    
    
    Private Shared Function ChooseAddIn(ByVal tokens As Collection(Of AddInToken)) As AddInToken
        If tokens.Count = 0 Then
            Console.WriteLine("No add-ins of this type are available")
            Return Nothing
        End If
        Console.WriteLine("{0} Available add-in(s):",tokens.Count.ToString())
        For i As Integer = 0 To tokens.Count - 1
            ' Show AddInToken properties.
            Console.WriteLine("[{0}] - {1}, Publisher: {2}, Version: {3}, Description: {4}", (i + 1).ToString(), tokens(i).Name, tokens(i).Publisher, tokens(i).Version, tokens(i).Description)
        Next i
        Console.WriteLine("Select add-in by number:")
        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 ChooseAddIn(tokens)
    End Function
    
    
    Friend Shared Function CreateBooks() As IList(Of BookInfo)
        Dim books As List(Of BookInfo) = New List(Of BookInfo)()
    
        Dim ParamId As String = ""
        Dim ParamAuthor As String = ""
        Dim ParamTitle As String = ""
        Dim ParamGenre As String = ""
        Dim ParamPrice As String = ""
        Dim ParamPublish_Date As String = ""
        Dim ParamDescription As String = ""
    
        Dim xDoc As XmlDocument = New XmlDocument()
        xDoc.Load("c:\Books.xml")
    
         Dim xRoot As XmlNode = xDoc.DocumentElement
         If xRoot.Name = "catalog" Then
            Dim bklist As XmlNodeList = xRoot.ChildNodes
            For Each bk As XmlNode In bklist
                ParamId = bk.Attributes(0).Value
                Dim dataItems As XmlNodeList = bk.ChildNodes
                Dim items As Integer = dataItems.Count
                For Each di As XmlNode In dataItems
                    Select Case di.Name
                        Case "author"
                            ParamAuthor = di.InnerText
                        Case "title"
                            ParamTitle = di.InnerText
                        Case "genre"
                            ParamGenre = di.InnerText
                         Case "price"
                            ParamPrice = di.InnerText
                         Case "publish_date"
                            ParamAuthor = di.InnerText
                         Case "description"
                            ParamDescription = di.InnerText
                          Case Else
                    End Select
    
                Next di
                books.Add(New MyBookInfo(ParamId, ParamAuthor, ParamTitle, ParamGenre, ParamPrice, ParamPublish_Date, ParamDescription))
            Next bk
    
         End If
        Return books
    End Function
    
    
    End Class
    
    Friend Class MyBookInfo
        Inherits BookInfo
        Private _id As String
        Private _author As String
        Private _title As String
        Private _genre As String
        Private _price As String
        Private _publish_date As String
        Private _description As String
    
        Public Sub New(ByVal id As String, ByVal author As String, ByVal title As String, ByVal genre As String, ByVal price As String, ByVal publish_date As String, ByVal description As String)
            _id = id
            _author = author
            _title = title
            _genre = genre
            _price = price
            _publish_date = publish_date
            _description = description
        End Sub
    
        Public Overrides Function ID() As String
            Return _id
        End Function
    
        Public Overrides Function Title() As String
            Return _title
        End Function
    
        Public Overrides Function Author() As String
            Return _author
        End Function
    
         Public Overrides Function Genre() As String
            Return _genre
         End Function
        Public Overrides Function Price() As String
            Return _price
        End Function
        Public Overrides Function Publish_Date() As String
            Return _publish_date
        End Function
        Public Overrides Function Description() As String
            Return _description
        End Function
    End Class
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Text;
    using LibraryContractsHAV;
    using System.AddIn.Hosting;
    using System.Xml;
    
    
    namespace ListAdaptersHost
    {
    class Program
    {
    static void Main(string[] args)
    {
    
        // In this example, the pipeline root is the current directory.
        String pipeRoot = Environment.CurrentDirectory;
    
        // Rebuild the cache of pipeline and add-in information.
        string[] warnings = AddInStore.Update(pipeRoot);
        if (warnings.Length > 0)
        {
            foreach (string one in warnings)
            {
                Console.WriteLine(one);
            }
        }
    
        // Find add-ins of type LibraryManager under the specified pipeline root directory.
        Collection<AddInToken> tokens = AddInStore.FindAddIns(typeof(LibraryManager), pipeRoot);
        // Determine which add-in to use.
        AddInToken selectedToken = ChooseAddIn(tokens);
    
        // Activate the selected AddInToken in a new
        // application domain with a specified security trust level.
        LibraryManager manager = selectedToken.Activate<LibraryManager>(AddInSecurityLevel.FullTrust);
    
        // Create a collection of books.
        IList<BookInfo> books = CreateBooks();
    
        // Show the collection count.
        Console.WriteLine("Number of books:  {0}",books.Count.ToString());
    
        // Have the add-in process the books.
        // The add-in will discount computer books by $20
        // and list their before and after prices. It
        // will also remove all horror books.
        manager.ProcessBooks(books);
    
        // List the genre of each book. There
        // should be no horror books.
        foreach (BookInfo bk in books)
        {
            Console.WriteLine(bk.Genre());
        }
    
        Console.WriteLine("Number of books: {0}", books.Count.ToString());
    
        Console.WriteLine();
        // Have the add-in pass a BookInfo object
        // of the best selling book.
        BookInfo bestBook = manager.GetBestSeller();
        Console.WriteLine("Best seller is {0} by {1}", bestBook.Title(), bestBook.Author());
    
        // Have the add-in show the sales tax rate.
        manager.Data("sales tax");
    
        AddInController ctrl = AddInController.GetAddInController(manager);
        ctrl.Shutdown();
        Console.WriteLine("Press any key to exit.");
        Console.ReadLine();
    }
    
    
    
    private static AddInToken ChooseAddIn(Collection<AddInToken> tokens)
    {
        if (tokens.Count == 0)
        {
            Console.WriteLine("No add-ins of this type are available");
            return null;
        }
        Console.WriteLine("{0} Available add-in(s):",tokens.Count.ToString());
        for (int i = 0; i < tokens.Count; i++)
        {
            // Show AddInToken properties.
            Console.WriteLine("[{0}] - {1}, Publisher: {2}, Version: {3}, Description: {4}",
                (i + 1).ToString(), tokens[i].Name, tokens[i].Publisher,
                tokens[i].Version, tokens[i].Description);
        }
        Console.WriteLine("Select add-in by number:");
        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 ChooseAddIn(tokens);
    }
    
    
    internal static IList<BookInfo> CreateBooks()
    {
        List<BookInfo> books = new List<BookInfo>();
    
        string ParamId = "";
        string ParamAuthor = "";
        string ParamTitle = "";
        string ParamGenre = "";
        string ParamPrice = "";
        string ParamPublish_Date = "";
        string ParamDescription = "";
    
        XmlDocument xDoc = new XmlDocument();
        xDoc.Load(@"c:\Books.xml");
    
         XmlNode xRoot = xDoc.DocumentElement;
         if (xRoot.Name == "catalog")
        {
            XmlNodeList bklist = xRoot.ChildNodes;
            foreach (XmlNode bk in bklist)
            {
                ParamId = bk.Attributes[0].Value;
                XmlNodeList dataItems = bk.ChildNodes;
                int items = dataItems.Count;
                foreach (XmlNode di in dataItems)
                {
                    switch (di.Name)
                    {
                        case "author":
                            ParamAuthor = di.InnerText;
                            break;
                        case "title":
                            ParamTitle = di.InnerText;
                            break;
                        case "genre":
                            ParamGenre = di.InnerText;
                            break;
                         case "price":
                            ParamPrice = di.InnerText;
                            break;
                         case "publish_date":
                            ParamAuthor = di.InnerText;
                            break;
                         case "description":
                            ParamDescription = di.InnerText;
                            break;
                          default:
                            break;
                    }
    
                }
                books.Add(new MyBookInfo(ParamId, ParamAuthor, ParamTitle, ParamGenre,
                                ParamPrice, ParamPublish_Date, ParamDescription));
            }
    
        }
        return books;
    }
    
    
    }
    
    class MyBookInfo : BookInfo
    {
        private string _id;
        private string _author;
        private string _title;
        private string _genre;
        private string _price;
        private string _publish_date;
        private string _description;
    
        public MyBookInfo(string id, string author, string title,
                            string genre, string price,
                            string publish_date, string description)
        {
            _id = id;
            _author = author;
            _title = title;
            _genre = genre;
            _price = price;
            _publish_date = publish_date;
            _description = description;
        }
    
        public override string ID()
        {
            return _id;
        }
    
        public override string Title()
        {
            return _title;
        }
    
        public override string Author()
        {
            return _author;
        }
    
         public override string Genre()
        {
            return _genre;
        }
        public override string Price()
        {
            return _price;
        }
        public override string Publish_Date()
        {
            return _publish_date;
        }
        public override string Description()
        {
            return _description;
        }
    }
    }
    

So erstellen Sie die Datendatei books.xml

  1. Fügen Sie dem Projekt BookStore eine neue XML-Datei hinzu. Geben Sie der Datei im Dialogfeld Neues Element hinzufügen den Namen books.xml.

  2. Ersetzen Sie den Standardinhalt von books.xml durch den XML-Code von Sample XML File (books.xml).

  3. Wählen Sie im Projektmappen-Explorer die Datei books.xml aus, und legen Sie unter Eigenschaften die Option In Ausgabeverzeichnis kopieren auf Immer kopieren fest.

Erstellen des Add-Ins

Ein Add-In implementiert die von der Add-In-Ansicht angegebenen Methoden. Diese Add-In-Methode implementiert die ProcessBooks-Methode. Die Methode führt die folgenden Operationen für eine Auflistung von BookInfo-Objekten aus, die vom Host an sie übergeben werden.

  • Setzt den Preis von allen Computerbüchern um 20 Prozent herab.

  • Entfernt alle Bücher mit Horrorgeschichten aus der Auflistung.

Dieses Add-In implementiert auch die GetBestSeller-Methode, indem sie ein BookInfo-Objekt übergibt, in dem der Bestseller für den Host beschrieben wird.

So erstellen Sie das Add-In

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

  2. Öffnen Sie in Visual Basic das Dialogfeld Eigenschaften für das Projekt, und löschen Sie mithilfe der Registerkarte Anwendung den Standardwert für Stammnamespace.

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

  4. Fügen Sie einen Projektverweis auf das Projekt AddInViews hinzu. Legen Sie unter Eigenschaften die Option Lokale Kopie für diesen Verweis auf False fest, damit die Assembly, auf die verwiesen wird, nicht in den lokalen Buildordner kopiert wird.

  5. Fügen Sie in der Klassendatei Verweise auf System.AddIn und die Namespaces des Add-In-Ansichtssegments hinzu.

  6. Verwenden Sie den folgenden Code für die Add-In-Anwendung.

    
    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports LibraryContractsBase
    Imports System.AddIn
    Imports System.IO
    
    Namespace SampleAddIn
    <AddIn("Books AddIn",Version:="1.0.0.0")> _
    Public Class BooksAddIn
        Inherits LibraryManager
        ' Calls methods that updates book data
        ' and removes books by genre.
        Public Overrides Sub ProcessBooks(ByVal books As IList(Of BookInfo))
            For i As Integer = 0 To books.Count - 1
                books(i) = UpdateBook(books(i))
            Next i
            RemoveGenre("horror", books)
        End Sub
    
        Public Overrides Function Data(ByVal txt As String) As String
            ' assumes txt = "sales tax"
            Dim rtxt As String = txt & "= 8.5%"
            Return rtxt
        End Function
    
        Friend Shared Function RemoveGenre(ByVal genre As String, ByVal books As IList(Of BookInfo)) As IList(Of BookInfo)
            ' Remove all horror books from the collection.
            Dim i As Integer = 0
            Do While i < books.Count
                If books(i).Genre().ToLower() = "horror" Then
                    books.RemoveAt(i)
                End If
                i += 1
            Loop
            Return books
        End Function
    
        ' Populate a BookInfo object with data
        ' about the best selling book.
        Public Overrides Function GetBestSeller() As BookInfo
            Dim ParamId As String = "bk999"
            Dim ParamAuthor As String = "Corets, Eva"
            Dim ParamTitle As String = "Cooking with Oberon"
            Dim ParamGenre As String = "Cooking"
            Dim ParamPrice As String = "7.95"
            Dim ParamPublish_Date As String = "2006-12-01"
            Dim ParamDescription As String = "Recipes for a post-apocalyptic society."
    
            Dim bestBook As MyBookInfo = New MyBookInfo(ParamId, ParamAuthor, ParamTitle, ParamGenre, ParamPrice, ParamPublish_Date, ParamDescription)
            Return bestBook
        End Function
    
        Friend Shared Function UpdateBook(ByVal bk As BookInfo) As BookInfo
            ' Discounts the price of all
            ' computer books by 20 percent.
            Dim ParamId As String = bk.ID()
            Dim ParamAuthor As String = bk.Author()
            Dim ParamTitle As String = bk.Title()
            Dim ParamGenre As String = bk.Genre()
            Dim ParamPrice As String = bk.Price()
            If ParamGenre.ToLower() = "computer" Then
                Dim oldprice As Double = Convert.ToDouble(ParamPrice)
                Dim newprice As Double = oldprice - (oldprice *.20)
                ParamPrice = newprice.ToString()
                If ParamPrice.IndexOf(".") = ParamPrice.Length - 4 Then
                    ParamPrice = ParamPrice.Substring(1, ParamPrice.Length - 1)
                End If
                Console.WriteLine("{0} - Old Price: {1}, New Price: {2}",ParamTitle,oldprice.ToString(),ParamPrice)
            End If
            Dim ParamPublish_Date As String = bk.Publish_Date()
            Dim ParamDescription As String = bk.Description()
    
            Dim bookUpdated As BookInfo = New MyBookInfo(ParamId, ParamAuthor, ParamTitle, ParamGenre, ParamPrice, ParamPublish_Date, ParamDescription)
    
            Return bookUpdated
    
        End Function
    
    End Class
    
    ' Creates a BookInfo object.
    Friend Class MyBookInfo
        Inherits BookInfo
        Private _id As String
        Private _author As String
        Private _title As String
        Private _genre As String
        Private _price As String
        Private _publish_date As String
        Private _description As String
    
        Public Sub New(ByVal id As String, ByVal author As String, ByVal title As String, ByVal genre As String, ByVal price As String, ByVal publish_date As String, ByVal description As String)
            _id = id
            _author = author
            _title = title
            _genre = genre
            _price = price
            _publish_date = publish_date
            _description = description
        End Sub
    
        Public Overrides Function ID() As String
            Return _id
        End Function
    
        Public Overrides Function Title() As String
            Return _title
        End Function
    
        Public Overrides Function Author() As String
            Return _author
        End Function
    
        Public Overrides Function Genre() As String
            Return _genre
        End Function
        Public Overrides Function Price() As String
            Return _price
        End Function
        Public Overrides Function Publish_Date() As String
            Return _publish_date
        End Function
        Public Overrides Function Description() As String
            Return _description
        End Function
    End Class
    
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using LibraryContractsBase;
    using System.AddIn;
    using System.IO;
    
    namespace BooksAddIn
    {
    [AddIn("Books AddIn",Description="Book Store Data",
           Publisher="Microsoft",Version="1.0.0.0")]
    
    public class BooksAddIn : LibraryManager
    {
        // Calls methods that updates book data
        // and removes books by their genre.
        public override void ProcessBooks(IList<BookInfo> books)
        {
            for (int i = 0; i < books.Count; i++)
            {
                books[i] = UpdateBook(books[i]);
            }
            RemoveGenre("horror", books);
        }
    
        public override string Data(string txt)
        {
            // assumes txt = "sales tax"
            string rtxt = txt + "= 8.5%";
            return rtxt;
        }
    
        internal static IList<BookInfo> RemoveGenre(string genre, IList<BookInfo> books)
        {
            // Remove all horror books from the collection.
            for (int i = 0; i < books.Count; i++)
            {
                if (books[i].Genre().ToLower() == "horror")
                    books.RemoveAt(i);
            }
            return books;
        }
    
        // Populate a BookInfo object with data
        // about the best selling book.
        public override BookInfo GetBestSeller()
        {
            string ParamId = "bk999";
            string ParamAuthor = "Corets, Eva";
            string ParamTitle = "Cooking with Oberon";
            string ParamGenre = "Cooking";
            string ParamPrice = "7.95";
            string ParamPublish_Date = "2006-12-01";
            string ParamDescription = "Recipes for a post-apocalyptic society.";
    
            MyBookInfo bestBook = new MyBookInfo(ParamId, ParamAuthor, ParamTitle, ParamGenre,
                                    ParamPrice, ParamPublish_Date, ParamDescription);
            return bestBook;
        }
    
        internal static BookInfo UpdateBook(BookInfo bk)
        {
            // Discounts the price of all
            // computer books by 20 percent.
            string ParamId = bk.ID();
            string ParamAuthor = bk.Author();
            string ParamTitle = bk.Title();
            string ParamGenre = bk.Genre();
            string ParamPrice = bk.Price();
            if (ParamGenre.ToLower() == "computer")
            {
                double oldprice = Convert.ToDouble(ParamPrice);
                double newprice = oldprice - (oldprice * .20);
                ParamPrice = newprice.ToString();
                if (ParamPrice.IndexOf(".") == ParamPrice.Length - 4)
                    ParamPrice = ParamPrice.Substring(1, ParamPrice.Length - 1);
                Console.WriteLine("{0} - Old Price: {1}, New Price: {2}",ParamTitle,oldprice.ToString(),ParamPrice);
            }
            string ParamPublish_Date = bk.Publish_Date();
            string ParamDescription = bk.Description();
    
            BookInfo bookUpdated = new MyBookInfo(ParamId, ParamAuthor, ParamTitle, ParamGenre,
                            ParamPrice, ParamPublish_Date, ParamDescription);
    
            return bookUpdated;
    
        }
    
    }
    
    // Creates a BookInfo object.
    class MyBookInfo : BookInfo
    {
        private string _id;
        private string _author;
        private string _title;
        private string _genre;
        private string _price;
        private string _publish_date;
        private string _description;
    
        public MyBookInfo(string id, string author, string title,
                            string genre, string price,
                            string publish_date, string description)
        {
            _id = id;
            _author = author;
            _title = title;
            _genre = genre;
            _price = price;
            _publish_date = publish_date;
            _description = description;
        }
    
        public override string ID()
        {
            return _id;
        }
    
        public override string Title()
        {
            return _title;
        }
    
        public override string Author()
        {
            return _author;
        }
    
        public override string Genre()
        {
            return _genre;
        }
        public override string Price()
        {
            return _price;
        }
        public override string Publish_Date()
        {
            return _publish_date;
        }
        public override string Description()
        {
            return _description;
        }
    }
    
    }
    

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, wie in der folgenden Tabelle dargestellt.

    Project

    Pfad

    BooksAddIn

    Pipeline\AddIns\CalcV1

    AddInSideAdapters

    Pipeline\AddInSideAdapters

    AddInViews

    Pipeline\AddInViews

    LibraryContracts

    Pipeline\Contracts

    BookStore

    Pipeline (oder ein eigenes Anwendungsverzeichnis)

    HostSideAdapters

    Pipeline\HostSideAdapters

    HostViews

    Pipeline (oder ein eigenes Anwendungsverzeichnis)

    HinweisHinweis

    Stellen Sie sicher, dass der Hostcode, der den Speicherort des Pipelinestammverzeichnisses angibt, geändert wird, wenn die Anwendung in einem anderen als dem Pipeline-Ordner gespeichert werden soll.

  2. Erstellen Sie die Visual Studio-Projektmappe.

    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 dem Add-In interagieren.

So führen Sie die Hostanwendung aus

  1. Gehen Sie an der Eingabeaufforderung zum Pipelinestammverzeichnis, und führen Sie die Hostanwendung aus. In diesem Beispiel ist die Hostanwendung BookStore.exe.

  2. Der Host sucht alle verfügbaren Add-Ins von seinem Typ und fordert Sie auf, ein Add-In auszuwählen. Geben Sie 1 für das einzige verfügbare Add-In ein.

    Das Add-In wird vom Host aktiviert und für mehrere Operationen verwendet, die die Bücherliste betreffen.

  3. Drücken Sie eine beliebige Taste, um die Anwendung zu schließen.

Siehe auch

Aufgaben

Exemplarische Vorgehensweise: Erstellen von erweiterbaren Anwendungen

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

Konzepte

Anforderungen für die Pipelineentwicklung

Verträge, Ansichten und Adapter

Pipeline-Entwicklung