Share via


Procédure pas à pas : passage de collections entre des hôtes et des compléments

Cette procédure pas à pas décrit comment créer un pipeline qui passe une collection d'objets personnalisés entre un complément et un hôte. Étant donné que les types de la collection ne sont pas sérialisables, des classes supplémentaires définissant des adaptateurs de vue en contrat et de contrat en vue doivent être ajoutées aux segments d'adaptateur pour que le flux de types puisse franchir la limite d'isolation.

Dans ce scénario, le complément met à jour une collection d'objets book (livre) pour l'hôte. Chaque objet book contient des méthodes qui obtiennent et définissent le titre du livre, l'éditeur, le prix et d'autres données.

Comme exemple, l'hôte crée une collection de livres ; le complément diminue de 20 % le prix de tous les livres informatiques et supprime tous les livres d'horreur de la collection. Le complément crée ensuite un objet book pour le livre le mieux vendu et le passe à l'hôte comme un objet unique.

Cette procédure pas à pas décrit les tâches suivantes :

  • Création d'une solution Visual Studio.

  • Création de la structure de répertoires du pipeline.

  • Création des contrats et vues pour les objets qui doivent être passés dans un sens et dans l'autre à travers la limite d'isolation.

  • Création des adaptateurs côté complément et côté hôte requis pour passer les objets à travers la limite d'isolation.

  • Création de l'hôte.

  • Création du complément.

  • Déploiement du pipeline.

  • Exécution de l'application hôte.

RemarqueRemarque

Une partie du code indiqué dans cette procédure pas à pas contient des références à des espace de noms superflues.Les étapes de la procédure reflètent correctement les références requises en Visual Studio.

Vous trouverez des exemples de code supplémentaires, ainsi que des présentations technologiques destinées aux clients des outils de génération de pipelines de compléments, sur le site Managed Extensibility and Add-In Framework (en anglais) de CodePlex.

Composants requis

Pour exécuter cette procédure pas à pas, vous devez disposer des composants suivants :

Création d'une solution Visual Studio

Utilisez une solution dans Visual Studio pour contenir les projets de vos segments de pipeline.

Pour créer la solution de pipeline

  1. Dans Visual Studio, créez un projet nommé LibraryContracts. Basez-le sur le modèle Bibliothèque de classes.

  2. Nommez la solution BooksPipeline.

Création de la structure de répertoires du pipeline

Le modèle de complément requiert que les assemblys du segment de pipeline soient placés dans une structure de répertoires spécifiée.

Pour créer la structure de répertoires du pipeline

  • Créez la structure de dossier suivante sur votre ordinateur. Vous pouvez la localiser n'importe où, y compris dans les dossiers de votre solution Visual Studio.

    Pipeline
      AddIns
        BooksAddIn
      AddInSideAdapters
      AddInViews
      Contracts
      HostSideAdapters
    

    Tous les noms de dossier doivent être spécifiés exactement comme indiqué ici, à l'exception du nom de dossier racine et des noms de dossiers de complément individuels. Cet exemple utilise Pipeline comme nom de dossier racine et BooksAddIn comme nom de dossier de complément.

    RemarqueRemarque

    Pour des raisons de commodité, la procédure pas à pas place l'application hôte dans le dossier racine de pipeline.À l'étape appropriée, la procédure pas à pas explique comment modifier le code si l'application est à un emplacement différent.

    Pour plus d'informations sur la structure des dossiers du pipeline, consultez Spécifications du développement de pipelines.

Création du contrat et des vues

Le segment de contrat pour ce pipeline définit deux interfaces :

  • Interface IBookInfoContract.

    Cette interface contient les méthodes, telles que Author, qui contiennent des informations sur un livre.

  • Interface ILibraryManagerContract.

    Cette interface contient la méthode ProcessBooks que le complément utilise pour traiter une collection de livres. Chaque livre représente un contrat IBookInfoContract. L'interface contient également la méthode GetBestSeller que le complément utilise pour fournir à l'hôte un objet book représentant le livre le mieux vendu.

Pour créer le contrat

  1. Dans la solution Visual Studio nommée BooksPipeline, ouvrez le projet LibraryContracts.

  2. En Visual Basic, ouvrez Propriétés pour le projet LibraryContracts et utilisez l'onglet Application pour supprimer la valeur par défaut fournie pour Espace de noms racine. Par défaut, Espace de noms racine a pour valeur le nom du projet.

  3. Dans l'Explorateur de solutions, ajoutez au projet des références aux assemblys suivants :

    Sytem.AddIn.Contract.dll

    System.AddIn.dll

  4. Dans le fichier de classe, ajoutez des références aux espaces de noms System.AddIn.Contract et System.AddIn.Pipeline.

  5. Dans le fichier de classe, remplacez la déclaration de classe par défaut par deux interfaces :

    • L'interface ILibraryManagerContract étant utilisée pour activer le complément, elle doit avoir l'attribut AddInContractAttribute.

    • L'interface IBookInfoContract représentant un objet passé entre l'hôte et le complément, elle ne requiert pas d'attribut.

    Les deux interfaces doivent hériter de l'interface IContract.

  6. Utilisez le code suivant pour ajouter les interfaces IBookInfoContract et ILibraryManagerContract.

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

Étant donné que la vue de complément et la vue hôte ont le même code, vous pouvez facilement créer ces vues en même temps. Elles diffèrent par un seul facteur : la vue de complément qui est utilisée pour activer ce segment du pipeline requiert l'attribut AddInBaseAttribute ; la vue hôte ne requiert pas d'attributs.

La vue de complément pour ce pipeline contient deux classes abstraites. La classe BookInfo fournit la vue pour l'interface IBookInfoContract et la classe LibraryManager fournit la vue pour l'interface ILibraryManagerContract.

Pour créer la vue de complément

  1. Ajoutez un nouveau projet nommé AddInViews à la solution BooksPipeline. Basez-le sur le modèle Bibliothèque de classes.

  2. En Visual Basic, ouvrez Propriétés pour le projet et utilisez l'onglet Application pour supprimer la valeur par défaut fournie pour Espace de noms racine.

  3. Dans l'Explorateur de solutions, ajoutez au projet AddInViews une référence à System.AddIn.dll.

  4. Renommez la classe par défaut du projet LibraryManager et définissez la classe comme abstract (MustInherit en Visual Basic).

  5. Dans le fichier de classe, ajoutez une référence à l'espace de noms System.AddIn.Pipeline.

  6. La classe LibraryManager étant utilisée pour activer le pipeline, vous pouvez appliquer l'attribut AddInBaseAttribute.

  7. Utilisez le code suivant pour terminer la classe LibraryManager abstraite.

    
    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. Ajoutez une classe abstract (classe MustInherit en Visual Basic) au projet et nommez-la BookInfo. La classe BookInfo représente un objet passé entre l'hôte et le complément. Cette classe n'est pas utilisée pour activer le pipeline, elle ne requiert donc pas d'attributs.

  9. Utilisez le code suivant pour terminer la classe BookInfo abstraite.

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

Pour créer la vue hôte

  1. Ajoutez un nouveau projet nommé HostViews à la solution BooksPipeline. Basez-le sur le modèle Bibliothèque de classes.

  2. En Visual Basic, ouvrez Propriétés pour le projet et utilisez l'onglet Application pour supprimer la valeur par défaut fournie pour Espace de noms racine.

  3. Renommez la classe par défaut du projet LibraryManager et définissez la classe comme abstract (MustInherit en Visual Basic).

  4. Utilisez le code suivant pour terminer la classe LibraryManager abstraite.

    
    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. Ajoutez une classe abstract (classe MustInherit en Visual Basic) au projet et nommez-la BookInfo.

  6. Utilisez le code suivant pour terminer la classe BookInfo abstraite.

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

Création de l'adaptateur côté complément

L'assembly d'adaptateur côté complément pour ce pipeline contient quatre classes d'adaptateur :

  • BookInfoContractToViewAddInAdapter

    Cet adaptateur est appelé lorsque l'hôte passe un objet BookInfo au complément, soit tout seul soit dans le cadre d'une collection. Cette classe convertit le contrat de l'objet BookInfo en vue. La classe hérite de la vue de complément et implémente les méthodes abstraites de la vue en appelant le contrat passé au constructeur de la classe.

    Le constructeur de cet adaptateur prend un contrat afin qu'un objet ContractHandle puisse être appliqué au contrat pour implémenter la gestion de la durée de vie.

    Remarque importanteImportant

    ContractHandle est critique pour la gestion de la durée de vie.Si vous ne parvenez pas à conserver une référence à l'objet ContractHandle, le garbage collection la récupérera, et le pipeline s'arrêtera quand le programme ne s'y attend pas.Cela peut provoquer des erreurs difficiles à diagnostiquer, telles que AppDomainUnloadedException.L'arrêt est une étape normale dans la vie d'un pipeline ; il est donc impossible pour le code de gestion de la durée de vie de détecter que cette condition est une erreur.

  • BookInfoViewToContractAddInAdapter

    Cet adaptateur est appelé lorsque le complément passe un objet BookInfo à l'hôte. Cette classe convertit la vue de complément de l'objet BookInfo en contrat. La classe hérite du contrat et implémente le contrat en appelant la vue de complément passée au constructeur de la classe. Cet adaptateur est marshalé vers l'hôte en tant que contrat.

  • LibraryManagerViewToContractAddInAdapter

    Il s'agit du type qui est retourné à l'hôte à partir de son appel pour activer le complément. Ce type est appelé lorsque l'hôte appelle le complément, notamment l'appel qui passe une collection d'objets hôtes (IList<BookInfo>) au complément. Cette classe convertit le contrat ILibraryManagerContract en vue hôte LibraryManager. Cette classe hérite de la vue hôte et implémente le contrat en appelant la vue passée à son constructeur.

    Étant donné qu'une collection de types personnalisés, les objets BookInfo, doit être marshalée à travers la limite d'isolation, cet adaptateur utilise la classe CollectionAdapters. Cette classe fournit des méthodes pour convertir une collection IList<T> en une collection IListContract<T>, ce qui permet à la collection de passer à travers la limite d'isolation pour atteindre l'autre côté du pipeline.

  • BookInfoAddInAdapter

    Les méthodes static (méthodesShared en Visual Basic) de cet adaptateur sont appelées par la classe LibraryManagerViewToContractAddInAdapter pour adapter un contrat ou une vue, ou retourner un contrat ou une vue existants. Cela empêche la création d'un adaptateur supplémentaire lorsqu'un objet effectue un aller-retour entre l'hôte et le complément.

Pour créer l'adaptateur côté complément

  1. Ajoutez un nouveau projet nommé AddInSideAdapters à la solution BooksPipeline. Basez-le sur le modèle Bibliothèque de classes.

  2. En Visual Basic, ouvrez Propriétés pour le projet et utilisez l'onglet Application pour supprimer la valeur par défaut fournie pour Espace de noms racine.

  3. Dans l'Explorateur de solutions, ajoutez au projet AddInSideAdapters des références aux assemblys suivants :

    System.AddIn.dll

    System.AddIn.Contract.dll

  4. Dans l'Explorateur de solutions, ajoutez au projet AddInSideAdapters des références aux projets suivants :

    AddInViews

    LibraryContracts

    Dans la référence Propriétés, affectez la valeur False à Copie locale pour ces références, afin d'empêcher que les assemblys référencés soient copiés dans le dossier de génération local. Les assemblys se trouvent dans le structure de répertoires du pipeline, comme décrit un peu loin dans la section « Déployer la procédure Pipeline » de cette procédure.

  5. Nommez le fichier de classe BookInfoContractToViewAddInAdapter.

  6. Dans le fichier de classe, ajoutez une référence à l'espace de noms System.AddIn.Pipeline.

  7. Utilisez le code suivant pour ajouter la classe BookInfoContractToViewAddInAdapter. La classe ne requiert pas d'attribut, car elle n'est pas utilisée pour activer le pipeline. La méthode GetSourceContract internal (Friend en Visual Basic) est utilisée par la classe BookInfoAddInAdapter pour éviter de créer un adaptateur supplémentaire lorsqu'un objet effectue un aller-retour entre l'hôte et le complément.

    
    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. Utilisez le code suivant pour ajouter la classe BookInfoViewToContractAddInAdapter au projet AddInSideAdapters. La classe ne requiert pas d'attribut, car elle n'est pas utilisée pour activer le pipeline. La méthode GetSourceView internal (Friend en Visual Basic) est utilisée par la classe BookInfoAddInAdapter pour éviter de créer un adaptateur supplémentaire lorsqu'un objet effectue un aller-retour entre l'hôte et le complément.

    
    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. Utilisez le code suivant pour ajouter la classe LibraryManagerViewToContractAddInAdapter au projet AddInSideAdapters. Cette classe requiert l'attribut AddInAdapterAttribute, car elle est utilisée pour activer le pipeline.

    La méthode ProcessBooks indique comment passer une liste de livres à travers la limite d'isolation. Elle utilise la méthode CollectionAdapters.ToIList pour convertir la liste. Pour convertir les objets de la liste, elle passe des délégués pour les méthodes d'adaptateur fournies par la classe BookInfoAddInAdapter.

    La méthode GetBestSeller indique comment passer un objet BookInfo unique à travers la limite d'isolation.

    
    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. Utilisez le code suivant pour ajouter la classe BookInfoAddInAdapter au projet AddInSideAdapters. La classe contient deux méthodes static (méthodes Shared en Visual Basic) : ContractToViewAdapter et ViewToContractAdapter. Les méthodes sont internal (Friend en Visual Basic) parce qu'elles sont utilisées uniquement par les autres classes d'adaptateur. Le but de ces méthodes est d'éviter de créer un adaptateur supplémentaire lorsqu'un objet effectue un aller-retour dans l'une ou l'autre direction entre l'hôte et le complément. Ces méthodes doivent être fournies pour les adaptateurs qui passent des objets à travers la limite d'isolation.

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

Création de l'adaptateur côté hôte

L'assembly d'adaptateur côté hôte pour ce pipeline contient quatre classes d'adaptateur :

  • BookInfoContractToViewHostAdapter

    Cet adaptateur est appelé lorsque le complément passe un objet BookInfo à l'hôte, soit tout seul soit dans le cadre d'une collection. Cette classe convertit le contrat de l'objet BookInfo en vue. La classe hérite de la vue hôte et implémente les méthodes abstraites de la vue en appelant le contrat passé au constructeur de la classe.

    Le constructeur de cet adaptateur prend un contrat pour son constructeur afin qu'un objet ContractHandle puisse être appliqué au contrat pour implémenter la gestion de la durée de vie.

    Remarque importanteImportant

    ContractHandle est critique pour la gestion de la durée de vie.Si vous ne parvenez pas à conserver une référence à l'objet ContractHandle, le garbage collection la récupérera, et le pipeline s'arrêtera quand le programme ne s'y attend pas.Cela peut provoquer des erreurs difficiles à diagnostiquer, telles que AppDomainUnloadedException.L'arrêt est une étape normale dans la vie d'un pipeline ; il est donc impossible pour le code de gestion de la durée de vie de détecter que cette condition est une erreur.

  • BookInfoViewToContractHostAdapter

    Cet adaptateur est appelé lorsque l'hôte passe un objet BookInfo au complément. Cette classe convertit la vue hôte de l'objet BookInfo en contrat. La classe hérite du contrat et implémente le contrat en appelant la vue de complément passée au constructeur de la classe. Cet adaptateur est marshalé vers le complément en tant que contrat.

  • LibraryManagerContractToViewHostAdapter

    Cet adaptateur est appelé lorsque l'hôte passe une collection d'objets BookInfo au complément. Le complément effectue son implémentation de la méthode ProcessBooks sur cette collection.

    Cette classe convertit la vue hôte de l'objet LibraryManager en contrat. Elle hérite du contrat et implémente le contrat en appelant la vue hôte passée au constructeur de la classe.

    Étant donné qu'une collection de types personnalisés, les objets BookInfo, doit être marshalée à travers la limite d'isolation, cet adaptateur utilise la classe CollectionAdapters. Cette classe fournit des méthodes pour convertir une collection IList<T> en une collection IListContract<T>, ce qui permet à la collection de passer à travers la limite d'isolation pour atteindre l'autre côté du pipeline.

  • BookInfoHostAdapter

    Cet adaptateur est appelé par la classe LibraryManagerViewToContractHostAdapter pour retourner tous les contrats ou vues existants pour l'adaptation au lieu de créer des instances pour l'appel. Cela empêche la création d'un adaptateur supplémentaire lorsqu'un objet effectue un aller-retour dans l'une ou l'autre direction entre l'hôte et le complément.

Pour créer l'adaptateur côté hôte

  1. Ajoutez un nouveau projet nommé HostSideAdapters à la solution BooksPipeline. Basez-le sur le modèle Bibliothèque de classes.

  2. En Visual Basic, ouvrez Propriétés pour le projet et utilisez l'onglet Application pour supprimer la valeur par défaut fournie pour Espace de noms racine.

  3. Dans l'Explorateur de solutions, ajoutez au projet HostSideAdapters des références aux assemblys suivants :

    System.AddIn.dll

    System.AddIn.Contract.dll

  4. Dans l'Explorateur de solutions, ajoutez au projet HostSideAdapters des références aux projets suivants :

    HostViews

    LibraryContracts

    Dans la référence Propriétés, affectez la valeur False à Copie locale pour ces références, afin d'empêcher que les assemblys référencés soient copiés dans le dossier de génération local.

  5. Dans le fichier de classe, ajoutez une référence à l'espace de noms System.AddIn.Pipeline.

  6. Utilisez le code suivant pour ajouter la classe BookInfoContractToViewHostAdapter. La classe ne requiert pas d'attribut, car elle n'est pas utilisée pour activer le pipeline. La méthode GetSourceContract internal (Friend en Visual Basic) est utilisée par la classe BookInfoAddInAdapter pour éviter de créer un adaptateur supplémentaire lorsqu'un objet effectue un aller-retour entre l'hôte et le complément.

    
    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. Utilisez le code suivant pour ajouter BookInfoViewToContractHostAdapter au projet HostSideAdapters. La classe ne requiert pas d'attribut, car elle n'est pas utilisée pour activer le pipeline. La méthode GetSourceView internal (Friend en Visual Basic) est utilisée par la classe BookInfoAddInAdapter pour éviter de créer un adaptateur supplémentaire lorsqu'un objet effectue un aller-retour entre l'hôte et le complément.

    
    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. Utilisez le code suivant pour ajouter LibraryManagerContractToViewHostAdapter au projet HostSideAdapters. Cette classe requiert l'attribut HostAdapterAttribute, car elle est utilisée pour activer le pipeline.

    La méthode ProcessBooks indique comment passer une liste de livres à travers la limite d'isolation. Elle utilise la méthode CollectionAdapters.ToIListContract pour convertir la liste. Pour convertir les objets de la liste, elle passe des délégués pour les méthodes d'adaptateur fournies par la classe BookInfoHostAdapter.

    La méthode GetBestSeller indique comment passer un objet BookInfo unique à travers la limite d'isolation.

    
    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. Utilisez le code suivant pour ajouter la classe BookInfoHostAdapter au projet HostSideAdapters. La classe contient deux méthodes static (méthodes Shared en Visual Basic) : ContractToViewAdapter et ViewToContractAdapter. Les méthodes sont internal (Friend en Visual Basic) parce qu'elles sont utilisées uniquement par les autres classes d'adaptateur. Le but de ces méthodes est d'éviter de créer un adaptateur supplémentaire lorsqu'un objet effectue un aller-retour dans l'une ou l'autre direction entre l'hôte et le complément. Ces méthodes doivent être fournies pour les adaptateurs qui passent des objets à travers la limite d'isolation.

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

Création de l'hôte

Une application hôte interagit avec le complément via la vue hôte. Elle utilise les méthodes d'activation et de découverte de complément fournies par les classes AddInStore et AddInToken pour effectuer les opérations suivantes :

  • Régénérer le cache du pipeline et les informations de complément.

  • Rechercher des compléments de type LibraryManager sous le répertoire racine du pipeline spécifié.

  • Inviter l'utilisateur à sélectionner le complément à utiliser. Dans cet exemple, un seul complément est disponible.

  • Activer le complément sélectionné dans un nouveau domaine d'application avec un niveau de confiance de sécurité spécifié.

  • Appeler la méthode ProcessBooks pour passer une collection d'objets BookInfo au complément. Le complément appelle son implémentation de la méthode ProcessBooks et procède à des opérations telles que la réduction de 20 % du prix des livres d'informatique.

  • Appelle la méthode GetBestSeller que le complément utilise pour retourner un objet BookInfo avec des informations sur le livre le mieux vendu.

  • Appelle la méthode Data pour obtenir le taux de TVA actuel à partir du complément. Cette méthode prend et retourne une chaîne qui constitue un type référence sérialisable sealed. Par conséquent, la méthode peut passer, via la limite d'isolation, de l'autre côté du pipeline sans utiliser d'adaptateurs de vue en contrat ou de contrat en vue.

L'hôte dispose d'une méthode CreateBooks qui crée une collection d'objets BookInfo. Cette méthode crée la collection en utilisant le fichier d'exemple books.xml qui est disponible à partir de Sample XML File (books.xml).

Pour créer l'hôte

  1. Ajoutez un nouveau projet nommé BookStore à la solution BooksPipeline. Basez-le sur le modèle Application console.

  2. En Visual Basic, ouvrez Propriétés pour le projet et utilisez l'onglet Application pour supprimer la valeur par défaut fournie pour Espace de noms racine.

  3. Dans l'Explorateur de solutions, ajoutez au projet BookStore une référence à l'assembly System.AddIn.dll.

  4. Ajoutez une référence de projet au projet HostViews. Dans la référence Propriétés, affectez la valeur False à Copie locale pour cette référence, afin d'empêcher que l'assembly référencé soit copié dans le dossier de génération local.

  5. En Visual Basic, modifiez le module en une classe :

    • Excluez le module par défaut du projet, puis ajoutez une classe nommée Program.

    • Remplacez le mot-clé Public par le mot-clé Friend.

    • Ajoutez une procédure Shared Sub Main() à la classe.

    • Utilisez l'onglet Application de la boîte de dialogue Propriétés du projet pour affecter à Objet de démarrage la valeur Sub Main.

  6. Dans le fichier de classe, ajoutez des références à System.AddIn.Pipeline et aux espaces de noms du segment de la vue hôte.

  7. Dans l'Explorateur de solutions, sélectionnez la solution puis, dans le menu Projet, sélectionnez Propriétés. Dans la boîte de dialogue Pages de propriétés de Solution, définissez le Projet de démarrage unique comme projet d'application hôte.

  8. Utilisez le code suivant pour l'application hôte.

    RemarqueRemarque

    Dans le code, modifiez l'emplacement à partir duquel le fichier books.xml est chargé en "books.xml",, afin que le fichier soit chargé à partir du dossier d'application.Si vous souhaitez placer l'application dans un emplacement autre que le dossier Pipeline, modifiez la ligne de code qui définit la variable addInRoot, afin que la variable contienne le chemin d'accès à votre structure de répertoires du pipeline.

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

Pour créer le fichier de données books.xml

  1. Ajoutez un nouveau fichier XML au projet BookStore. Dans la boîte de dialogue Ajouter un nouvel élément, nommez le fichier books.xml.

  2. Remplacez le contenu par défaut de books.xml par le XML provenant de Sample XML File (books.xml).

  3. Dans l'Explorateur de solutions, sélectionnez books.xml, et dans Propriétés, affectez à Copier dans le répertoire de sortie la valeur Toujours copier.

Création du complément

Un complément implémente les méthodes spécifiées par la vue de complément. Ce complément implémente la méthode ProcessBooks. La méthode exécute les opérations suivantes sur une collection d'objets BookInfo que l'hôte lui passe :

  • Diminue de 20 % le prix de tous les livres informatiques.

  • Supprime tous les livres d'horreur de la collection.

Ce complément implémente également la méthode GetBestSeller en passant un objet BookInfo qui décrit le livre le mieux vendu à l'hôte.

Pour créer le complément

  1. Ajoutez un nouveau projet nommé BooksAddin à la solution BooksPipeline. Basez-le sur le modèle Bibliothèque de classes.

  2. En Visual Basic, ouvrez Propriétés pour le projet et utilisez l'onglet Application pour supprimer la valeur par défaut fournie pour Espace de noms racine.

  3. Dans l'Explorateur de solutions, ajoutez au projet BooksAddin une référence à l'assembly System.AddIn.dll.

  4. Ajoutez une référence de projet au projet AddInViews. Dans la référence Propriétés, affectez la valeur False à Copie locale pour cette référence, afin d'empêcher que l'assembly référencé soit copié dans le dossier de génération local.

  5. Dans le fichier de classe, ajoutez des références à System.AddIn et aux espaces de noms du segment de la vue de complément.

  6. Utilisez le code suivant pour l'application de complément.

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

Déploiement du pipeline

Vous êtes maintenant prêt à générer et déployer les segments de complément vers la structure de répertoires du pipeline requise.

Pour déployer les segments vers le pipeline

  1. Pour chaque projet dans la solution, utilisez l'onglet Génération de Propriétés du projet (onglet Compiler en Visual Basic) pour définir la valeur du Chemin de sortie (Chemin de sortie de la génération en Visual Basic), comme indiqué dans le tableau suivant.

    Projet

    Chemin d'accès

    BooksAddIn

    Pipeline\AddIns\CalcV1

    AddInSideAdapters

    Pipeline\AddInSideAdapters

    AddInViews

    Pipeline\AddInViews

    LibraryContracts

    Pipeline\Contracts

    BookStore

    Pipeline (ou votre propre répertoire de l'application)

    HostSideAdapters

    Pipeline\HostSideAdapters

    HostViews

    Pipeline (ou votre propre répertoire de l'application)

    RemarqueRemarque

    Si vous avez décidé de mettre votre application dans un emplacement autre que le dossier Pipeline, veillez à modifier le code hôte qui spécifie l'emplacement du répertoire racine du pipeline.

  2. Générez la solution Visual Studio.

    Pour plus d'informations sur le déploiement vers le pipeline, consultez Spécifications du développement de pipelines.

Exécution de l'application hôte

Vous êtes maintenant prêt à exécuter l'hôte et à interagir avec le complément.

Pour exécuter l'application hôte

  1. À l'invite de commandes, accédez au répertoire racine du pipeline et exécutez l'application hôte. Dans cet exemple, l'application hôte est BookStore.exe.

  2. L'hôte recherche tous les compléments disponibles de son type et vous invite à sélectionner un complément. Entrez 1 pour le seul complément disponible.

    L'hôte active le complément et l'utilise pour effectuer plusieurs opérations dans la liste de livres.

  3. Appuyez sur n'importe quelle touche pour fermer l'application.

Voir aussi

Tâches

Procédure pas à pas : création d'une application extensible

Procédure pas à pas : activation de la compatibilité descendante lorsque votre hôte change

Concepts

Spécifications du développement de pipelines

Contrats, vues et adaptateurs

Développement de pipeline