Demonstra Passo a passo: Coleções de passagem entre Hosts e suplementos
Esta explicação passo a passo descreve como criar um pipeline que passa de uma coleção de objetos personalizados entre um suplemento e um host. Porque os tipos de coleção não são serializáveis, adicionais classes que definem o modo de exibição-para-contrato e adaptadores de exibição de contrato devem ser adicionados aos segmentos de adaptador para que o fluxo de tipos pode cruzar o limite de isolamento.
Nesse cenário, o suplemento atualiza uma coleção de objetos de catálogo para o host. Cada objeto de catálogo contém métodos que obtém e definir o título do livro, Editor, preço e outros dados.
Como uma demonstração, o host cria uma coleção de livros; o suplemento diminui o preço de todos os livros de informática em 20 por cento e remove todos os livros de horror da coleção. O add-in, em seguida, cria um novo objeto de catálogo para o catálogo de endereços mais vendido e passa para o host como um único objeto.
Essa explicação passo a passo ilustra as seguintes tarefas:
Criando uma solução de Visual Studio.
Criando a estrutura do diretório de pipeline.
Criando os contratos e exibições para objetos que devem ser passados de e para trás entre o limite de isolamento.
Criando os adaptadores de adicionar no lado e do lado do host, necessários para passar objetos entre o limite de isolamento.
Criando o host.
Criando o suplemento.
Implantando o pipeline.
Executando o aplicativo host.
Observação
Parte do código mostrado nesta explicação contém referências a namespace irrelevantes.As etapas de explicação passo a passo refletem com precisão as referências necessárias em Visual Studio.
Você pode encontrar o código de exemplo adicionais e customer technology previews das ferramentas para construção suplemento tubulações, na site extensibilidade gerenciada e a estrutura de suplemento no CodePlex.
Pré-requisitos
Para completar este passo a passo, são necessários os seguintes componentes:
Visual Studio.
O arquivo de exemplo do Books. XML, pode ser copiado de Sample XML File (books.xml).
Criação de uma solução de Visual Studio
Use uma solução em Visual Studio para conter projetos dos seus segmentos de pipeline.
Para criar a solução de pipeline
No Visual Studio, crie um novo projeto chamado LibraryContracts. Baseá-lo na Biblioteca de classe modelo.
Nomeie a solução BooksPipeline.
Criando a estrutura do diretório de Pipeline
O modelo de suplemento requer que os assemblies do segmento de pipeline sejam colocados em uma estrutura de diretório especificado.
Para criar a estrutura do diretório de pipeline
Crie a seguinte estrutura de pasta no seu computador. Você pode localizá-lo em qualquer lugar, inclusive dentro das pastas de sua solução de Visual Studio.
Pipeline AddIns BooksAddIn AddInSideAdapters AddInViews Contracts HostSideAdapters
Todos os nomes de pasta devem ser especificados exatamente como mostrado aqui, exceto para o nome da pasta raiz e os nomes das pastas individuais de suplemento. Este exemplo usa Pipeline como o nome da pasta raiz e BooksAddIn como o nome do suplemento pasta.
Observação
Para sua conveniência, a explicação coloca o aplicativo host na pasta raiz de pipeline.Na etapa de apropriado, a explicação passo a passo explica como alterar o código se o aplicativo estiver em um local diferente.
Para obter mais informações sobre a estrutura de pastas do pipeline, consulte Requisitos de desenvolvimento de pipeline.
Criação do contrato e modos de exibição
O segmento de contrato para esse pipeline define duas interfaces:
A interface IBookInfoContract.
Essa interface contém métodos, como Author, que contêm informações sobre o catálogo.
A interface ILibraryManagerContract.
Essa interface contém o ProcessBooks método que o suplemento usa para processar uma coleção de livros. Cada livro representa um IBookInfoContract contrato. A interface também contém o GetBestSeller método que o suplemento usa para fornecer um objeto de catálogo, que representa o catálogo de mais vendido, para o host.
Para criar o contrato.
Na solução de Visual Studio chamada BooksPipeline, abra o LibraryContracts project.
No Visual Basic, abra Propriedades para o LibraryContracts de projeto e usar o aplicativo guia para excluir o valor padrão fornecido para namespace raiz. Por padrão, namespace raiz é definida como o nome do projeto.
Em Solution Explorer, adicione referências aos assemblies seguintes ao projeto:
Sytem.addin.Contract.dll
System.addin.dll
No arquivo de classe, adicionar referências para o System.AddIn.Contract e System.AddIn.Pipeline namespaces.
No arquivo de classe, substitua a declaração de classe padrão com duas interfaces:
O ILibraryManagerContract interface é usada para ativar o add-in, portanto, ele deve ter o AddInContractAttribute atributo.
O IBookInfoContract interface representa um objeto que é transmitido entre o host e o suplemento, para que ele não requer o atributo.
Ambas as interfaces devem herdar de IContract interface.
Use o código a seguir para adicionar o IBookInfoContract e ILibraryManagerContract interfaces.
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(); } }
Porque o modo de exibição do suplemento e o modo de exibição de host tem o mesmo código, você pode criar facilmente os modos de exibição ao mesmo tempo. Diferem apenas um fator: a exibição de add-in que é usada para ativar esse segmento do pipeline requer o AddInBaseAttribute atributo; o modo de exibição do host não requer quaisquer atributos.
A exibição do suplemento para esse pipeline contém duas classes abstratas. O BookInfo classe fornece o modo de exibição para o IBookInfoContract interface e o LibraryManager classe fornece o modo de exibição para o ILibraryManagerContract interface.
Para criar a exibição do suplemento
Adicionar um novo projeto chamado AddInViews para o BooksPipeline solução. Baseá-lo na Biblioteca de classe modelo.
No Visual Basic, abra Propriedades para o projeto e use o aplicativo guia para excluir o valor padrão fornecido para namespace raiz.
Em Solution Explorer, adicione uma referência a System.AddIn.dll para o AddInViews project.
Renomeie a classe do projeto padrão LibraryManagere tornar a classe abstract (MustInherit em Visual Basic).
No arquivo de classe, adicione uma referência para o System.AddIn.Pipeline namespace.
O LibraryManager classe é usada para ativar o pipeline, portanto, você deve aplicar o AddInBaseAttribute atributo.
Use o seguinte código para concluir o resumo LibraryManager classe.
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); } }
Adicionar um abstract classe (MustInherit classe Visual Basic) para o projeto e denomine BookInfo. O BookInfo classe representa um objeto que é transmitido entre o host e o suplemento. Essa classe não é usada para ativar o pipeline, para que ele não requer quaisquer atributos.
Use o seguinte código para concluir o resumo BookInfo classe.
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(); } }
Para criar a exibição de host
Adicionar um novo projeto chamado HostViews para o BooksPipeline solução. Baseá-lo na Biblioteca de classe modelo.
No Visual Basic, abra Propriedades para o projeto e use o aplicativo guia para excluir o valor padrão fornecido para namespace raiz.
Renomeie a classe do projeto padrão LibraryManagere tornar a classe abstract (MustInherit em Visual Basic).
Use o seguinte código para concluir o resumo LibraryManager classe.
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); } }
Adicionar um abstract classe (MustInherit classe Visual Basic) para o projeto e denomine BookInfo.
Use o seguinte código para concluir o resumo BookInfo classe.
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(); } }
Criação do adaptador de adicionar no lado
O assembly de adicionar no lado adaptador para esse pipeline contém quatro classes de adaptador:
BookInfoContractToViewAddInAdapter
Este adaptador é chamado quando o host transmitirá um BookInfo o objeto para o suplemento, sozinha ou como parte de uma coleção. Essa classe converte o contrato com o BookInfo objeto para um modo de exibição. A classe herda o modo de exibição do suplemento e implementa os métodos abstratos do modo de exibição chamando o contrato que é passado para o construtor da classe.
O construtor para este adaptador leva a um contrato, para que uma ContractHandle objeto podem ser aplicadas ao contrato para implementar o gerenciamento do ciclo de vida.
Observação
O ContractHandle é fundamental para o gerenciamento do ciclo de vida.Se você deixar de manter uma referência para o ContractHandle , coleta de lixo será solicitá-lo, e objeto pipeline será desligado quando o seu programa não espera o proprietário.Isso pode levar a erros que são difíceis de diagnosticar, como AppDomainUnloadedException.Desligamento é um estágio normal na vida de um pipeline, portanto não há nenhuma maneira para o código de gerenciamento da vida útil detectar que essa condição é um erro.
BookInfoViewToContractAddInAdapter
Este adaptador é chamado quando o add-in passa um BookInfo o objeto para o host. Essa classe converte a exibição do suplemento do BookInfo o objeto para um contrato. A classe herda a partir do contrato e implementa o contrato chamando a exibição de add-in que é passada para o construtor da classe. Este adaptador é empacotado para o host como um contrato.
LibraryManagerViewToContractAddInAdapter
Este é o tipo retornado para o host de sua chamada para ativar o add-in. Esse tipo é chamado quando o host chama o suplemento, incluindo a chamada que transmite uma coleção de objetos do host (IList<BookInfo>) para o add-in. Essa classe converte o contrato de ILibraryManagerContract para o modo de exibição de host LibraryManager. Esta classe herda o modo de exibição do host e implementa o contrato chamando o modo de exibição que é passado para o construtor.
Porque uma coleção de tipos personalizados, o BookInfo objetos, deve ser empacotado em um limite de isolamento, este adaptador usa o CollectionAdapters classe. Essa classe fornece métodos para converter um IList<T> coleção para um IListContract<T> a coleção, que permite que a coleção de ultrapassar o limite de isolamento para o outro lado do pipeline.
BookInfoAddInAdapter
O static métodos (Shared métodos em Visual Basic) do adaptador são chamados pela LibraryManagerViewToContractAddInAdapter classe para adaptar-se de um contrato ou modo de exibição, ou para retornar a um contrato existente ou modo de exibição. Isso impede que a criação de um adaptador adicional quando um objeto faz uma viagem entre o host e o suplemento.
Para criar o adaptador de adicionar no lado
Adicionar um novo projeto chamado AddInSideAdapters para o BooksPipeline solução. Baseá-lo na Biblioteca de classe modelo.
No Visual Basic, abra Propriedades para o projeto e use o aplicativo guia para excluir o valor padrão fornecido para namespace raiz.
Em Solution Explorer, adicionar referências aos seguintes assemblies para o AddInSideAdapters projeto:
System.addin.dll
System.addin.Contract.dll
Em Solution Explorer, adicionar referências para os projetos a seguir para o AddInSideAdapters projeto:
AddInViews
LibraryContracts
Na referência de Propriedades, defina Copy Local para False para essas referências para impedir que os assemblies referenciados sejam copiadas para o local pasta de compilação. Os assemblies estará localizados na estrutura do diretório de pipeline, conforme descrito em "Implantando o Pipeline" procedimento posteriormente nesta explicação passo a passo.
Nomeie o arquivo de classe BookInfoContractToViewAddInAdapter.
No arquivo de classe, adicione uma referência para o System.AddIn.Pipeline namespace.
Use o código a seguir para adicionar o BookInfoContractToViewAddInAdapter classe. A classe não requer um atributo porque ele não é usado para ativar o pipeline. O internal (Friend em Visual Basic) GetSourceContract método é usado pelo BookInfoAddInAdapter classe para evitar a criação de um adaptador adicional quando um objeto faz uma viagem entre o host e o add-in.
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; } } }
Use o código a seguir para adicionar o BookInfoViewToContractAddInAdapter de classe para o AddInSideAdapters project. A classe não requer um atributo porque ele não é usado para ativar o pipeline. O internal (Friend em Visual Basic) GetSourceView método é usado pelo BookInfoAddInAdapter classe para evitar a criação de um adaptador adicional quando um objeto faz uma viagem entre o host e o add-in.
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; } } }
Use o código a seguir para adicionar o LibraryManagerViewToContractAddInAdapter de classe para o AddInSideAdapters project. Essa classe requer o AddInAdapterAttribute de atributo, porque ele é usado para ativar o pipeline.
O ProcessBooks método mostra como passar uma lista de livros, entre o limite de isolamento. Ele usa o CollectionAdapters.ToIList método para converter a lista. Para converter os objetos na lista, ele passa a delegados para os métodos do adaptador fornecidos pelo BookInfoAddInAdapter classe.
O GetBestSeller método mostra como passar um único BookInfo o objeto entre o limite de isolamento.
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; } } }
Use o código a seguir para adicionar o BookInfoAddInAdapter de classe para o AddInSideAdapters project. A classe contém dois static métodos (Shared métodos em Visual Basic): ContractToViewAdapter e ViewToContractAdapter. Os métodos são internal (Friend em Visual Basic) porque eles são usados somente por outro adaptador classes. A finalidade desses métodos é evitar a criação de um adaptador extra quando um objeto faz uma viagem em qualquer direção entre o host e o suplemento. Esses métodos devem ser fornecidos para adaptadores que passam objetos entre o limite de isolamento.
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); } } } }
Criando o adaptador de Host
Este assembly do adaptador no lado do host para esse pipeline contém quatro classes de adaptador:
BookInfoContractToViewHostAdapter
Este adaptador é chamado quando o add-in passa um BookInfo o objeto para o host, por si só, ou como parte de uma coleção. Essa classe converte o contrato com o BookInfo objeto para um modo de exibição. A classe herda o modo de exibição do host e implementa os métodos abstratos do modo de exibição chamando o contrato que é passado para o construtor da classe.
O construtor para este adaptador leva a um contrato para seu construtor, para que uma ContractHandle objeto podem ser aplicadas ao contrato para implementar o gerenciamento do ciclo de vida.
Observação
O ContractHandle é fundamental para o gerenciamento do ciclo de vida.Se você deixar de manter uma referência para o ContractHandle , coleta de lixo será solicitá-lo, e objeto pipeline será desligado quando o seu programa não espera o proprietário.Isso pode levar a erros que são difíceis de diagnosticar, como AppDomainUnloadedException.Desligamento é um estágio normal na vida de um pipeline, portanto não há nenhuma maneira para o código de gerenciamento da vida útil detectar que essa condição é um erro.
BookInfoViewToContractHostAdapter
Este adaptador é chamado quando o host transmitirá um BookInfo o objeto para o add-in. Essa classe converte o modo de exibição de host de BookInfo objeto para um contrato. A classe herda a partir do contrato e implementa o contrato chamando a exibição de add-in que é passada para o construtor da classe. Este adaptador é empacotado para o add-in como um contrato.
LibraryManagerContractToViewHostAdapter
Este adaptador é chamado quando o host passa uma coleção de BookInfo objetos add-in. O suplemento executa sua implementação da ProcessBooks método na coleção.
Essa classe converte o modo de exibição de host de LibraryManager objeto para um contrato. Ele herda a partir do contrato e implementa o contrato chamando o modo de exibição de host é passado para o construtor da classe.
Porque uma coleção de tipos personalizados, o BookInfo objetos, deve ser empacotado em um limite de isolamento, este adaptador usa o CollectionAdapters classe. Essa classe fornece métodos para converter um IList<T> coleção para um IListContract<T> a coleção, que permite que a coleção de ultrapassar o limite de isolamento para o outro lado do pipeline.
BookInfoHostAdapter
Este adaptador é chamado pelo LibraryManagerViewToContractHostAdapter classe para retornar qualquer contratos existentes ou a modos de exibição para a adaptação em vez de criar novas instâncias da chamada. Isso impede a criação de um adaptador extra, quando um objeto faz uma viagem em qualquer direção entre o host e o suplemento.
Para criar o adaptador de host
Adicionar um novo projeto chamado HostSideAdapters para o BooksPipeline solução. Baseá-lo na Biblioteca de classe modelo.
No Visual Basic, abra Propriedades para o projeto e use o aplicativo guia para excluir o valor padrão fornecido para namespace raiz.
Em Solution Explorer, adicionar referências aos seguintes assemblies para o HostSideAdapters projeto:
System.addin.dll
System.addin.Contract.dll
Em Solution Explorer, adicionar referências para os projetos a seguir para o HostSideAdapters projeto:
HostViews
LibraryContracts
Na referência de Propriedades, defina Copy Local para False para essas referências para impedir que os assemblies referenciados sejam copiadas para o local pasta de compilação.
No arquivo de classe, adicione uma referência para o System.AddIn.Pipeline namespace.
Use o código a seguir para adicionar o BookInfoContractToViewHostAdapter classe. A classe não requer um atributo porque ele não é usado para ativar o pipeline. O internal (Friend em Visual Basic) GetSourceContract método é usado pelo BookInfoAddInAdapter classe para evitar a criação de um adaptador extra, quando um objeto faz uma viagem entre o host e o add-in.
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; } } }
Use o código a seguir para adicionar o BookInfoViewToContractHostAdapter para o HostSideAdapters project. A classe não requer um atributo porque ele não é usado para ativar o pipeline. O internal (Friend em Visual Basic) GetSourceView método é usado pelo BookInfoAddInAdapter classe para evitar a criação de um adaptador extra, quando um objeto faz uma viagem entre o host e o add-in.
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; } } }
Use o código a seguir para adicionar o LibraryManagerContractToViewHostAdapter para o HostSideAdapters project. Essa classe requer o HostAdapterAttribute de atributo, porque ele é usado para ativar o pipeline.
O ProcessBooks método mostra como passar uma lista de livros, entre o limite de isolamento. Ele usa o CollectionAdapters.ToIListContract método para converter a lista. Para converter os objetos na lista, ele passa a delegados para os métodos do adaptador fornecidos pelo BookInfoHostAdapter classe.
O GetBestSeller método mostra como passar um único BookInfo o objeto entre o limite de isolamento.
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; } } }
Use o código a seguir para adicionar o BookInfoHostAdapter de classe para o HostSideAdapters project. A classe contém dois static métodos (Shared métodos em Visual Basic): ContractToViewAdapter e ViewToContractAdapter. Os métodos são internal (Friend em Visual Basic) porque eles são usados somente por outro adaptador classes. A finalidade desses métodos é evitar a criação de um adaptador extra quando um objeto faz uma viagem em qualquer direção entre o host e o suplemento. Esses métodos devem ser fornecidos para adaptadores que passam objetos entre o limite de isolamento.
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); } } } }
Criação do Host
Um aplicativo host interage com o suplemento por meio da exibição do host. Ele usa o suplemento de detecção e ativação métodos fornecidos pelo AddInStore e AddInToken classes para fazer o seguinte:
Reconstrua o cache das informações de pipeline e o suplemento.
Localizar suplementos do tipo LibraryManager sob o diretório de raiz do pipeline especificado.
Solicite ao usuário selecionar o suplemento para usar. Neste exemplo, apenas um add-in está disponível.
Ative o suplemento selecionado em um novo domínio de aplicativo com um nível de confiança de segurança especificado.
Chamar o ProcessBooks método para passar uma coleção de BookInfo objetos add-in. O add-in chama a sua implementação da ProcessBooks método e executa funções como, por exemplo, livros de informática de desconto por 20 por cento.
Chamadas a GetBestSeller método que o suplemento usa para retornar um BookInfo o objeto com informações sobre o catálogo mais vendidos.
Chamadas de Data método para obter a taxa atual de imposto sobre vendas do add-in. Esse método leva e retorna um string que é um tipo de referência de serializável lacrado. Como resultado, o método pode ser passado sobre o limite de isolamento para o outro lado do canal sem usar o modo de exibição-para-contrato ou contrato-para-exibição adaptadores.
O host tem uma CreateBooks método que cria uma coleção de BookInfo objetos. Esse método cria a coleção usando o arquivo Books. XML de exemplo que está disponível em Sample XML File (books.xml).
Para criar o host
Adicionar um novo projeto chamado livraria para o BooksPipeline solução. Baseá-lo sobre o O aplicativo de Console modelo.
No Visual Basic, abra Propriedades para o projeto e use o aplicativo guia para excluir o valor padrão fornecido para namespace raiz.
Em Solution Explorer, adicione uma referência ao assembly System.AddIn.dll para o livraria project.
Adicione uma referência para o HostViews project. Na referência de Propriedades, defina Copy Local para False para essa referência, para impedir que o assembly referenciado sejam copiadas para a pasta build do local.
No Visual Basic, altere o módulo a uma classe:
Excluir o módulo padrão do projeto e, em seguida, adicione uma classe chamada Program.
Substituir o Public palavra-chave com o Friend palavra-chave.
Adicionar um Shared Sub Main() procedimento para a classe.
Uso o aplicativo guia da Propriedades do projeto caixa de diálogo para definir o objeto de inicialização para Sub Main.
No arquivo de classe, adicionar referências para o System.AddIn.Pipeline e namespaces de segmento do host de exibição.
Em Solution Explorer, selecione a solução e o projeto menu escolha Propriedades. No Solution Property Pages caixa de diálogo, definir o Único projeto de inicialização ser este projeto de aplicativo do host.
Use o seguinte código para o aplicativo host.
Observação
No código, alterar o local do qual o Books. XML arquivo é carregado para "Books", para que o arquivo é carregado a partir da pasta de aplicativo.Se você deseja colocar o aplicativo em um local diferente do Pipeline pasta, altere a linha de código que define o addInRoot variável para que a variável contém o caminho para a sua estrutura de diretório de 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; } } }
Para criar o arquivo de dados do Books. XML
Adicionar um novo arquivo XML para o livraria project. No Add New Item caixa de diálogo, nomeie o arquivo Books. XML.
Substituir o conteúdo padrão de Books. XML com o XML do Sample XML File (books.xml).
No Solution Explorer, selecione Books. XMLe em Propriedades set Copy to Output Directory para Copy always.
Criando o suplemento
Um suplemento implementa os métodos especificados pelo modo de exibição do suplemento. Este suplemento implementa o ProcessBooks método. O método executa as seguintes operações em uma coleção de BookInfo objetos que o host transmitirá a ele:
Descontos o preço de todos os livros de informática em 20 por cento.
Remove todos os livros de horror da coleção.
Este suplemento também implementa o GetBestSeller método passando um BookInfo objeto que descreve o livro mais vendido no host.
Para criar o suplemento
Adicionar um novo projeto chamado BooksAddin para o BooksPipeline solução. Baseá-lo na Biblioteca de classe modelo.
No Visual Basic, abra Propriedades para o projeto e use o aplicativo guia para excluir o valor padrão fornecido para namespace raiz.
Em Solution Explorer, adicione uma referência ao assembly System.AddIn.dll para o BooksAddin project.
Adicione uma referência para o AddInViews project. Na referência de Propriedades, defina Copy Local para False para essa referência, para impedir que o assembly referenciado sejam copiadas para a pasta build do local.
No arquivo de classe, adicionar referências para o System.AddIn e namespaces de segmento de exibição do suplemento.
Use o seguinte código para o suplemento de aplicativo.
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; } } }
Implantando o Pipeline
Agora você está pronto para criar e implantar os segmentos de adicionar a estrutura do diretório de pipeline necessários.
Para implantar os segmentos de pipeline
Para cada projeto na solução, use o Build guia de Propriedades do projeto (o compilar guia Visual Basic) para definir o valor da caminho de saída (o Build output path em Visual Basic) conforme mostrado na tabela a seguir.
Project
Caminho
BooksAddIn
Pipeline\AddIns\CalcV1
AddInSideAdapters
Pipeline\AddInSideAdapters
AddInViews
Pipeline\AddInViews
LibraryContracts
Pipeline\Contracts
Livraria
Pipeline (ou seu próprio diretório de aplicativo)
HostSideAdapters
Pipeline\HostSideAdapters
HostViews
Pipeline (ou seu próprio diretório de aplicativo)
Observação
Se você decidiu colocar seu aplicativo em um local diferente do Pipeline a pasta, certifique-se de alterar o código do host que especifica o local do diretório raiz pipeline.
Crie a solução de Visual Studio.
Para obter informações sobre como implantar o pipeline, consulte Requisitos de desenvolvimento de pipeline.
Executando o aplicativo Host
Agora você está pronto para executar o host e interagir com o suplemento.
Para executar o aplicativo host
No prompt de comando, vá para o diretório raiz do pipeline e executar o aplicativo host. Neste exemplo, o aplicativo host é BookStore.exe.
O host localiza todos os suplementos disponíveis do seu tipo e solicita que você selecione um add-in. Digite 1 para o suplemento só está disponível.
O host ativa o add-in e o usa para realizar várias operações na lista de livros.
Pressione qualquer tecla para fechar o aplicativo.
Consulte também
Tarefas
Demonstra Passo a passo: Criando um aplicativo extensível
Conceitos
Requisitos de desenvolvimento de pipeline