연습: 호스트와 추가 기능 간의 컬렉션 전달

이 연습에서는 추가 기능과 호스트 간에 사용자 지정 개체 컬렉션을 전달하는 파이프라인을 만드는 방법에 대해 설명합니다. 컬렉션의 형식이 serialize 가능한 형식이 아니므로 뷰에서 계약으로 변환하는 어댑터 및 계약에서 뷰로 변환하는 어댑터를 정의하는 추가 클래스를 어댑터 세그먼트에 추가하여 형식 흐름이 격리 경계를 지날 수 있도록 해야 합니다.

이 시나리오에서 추가 기능은 호스트의 서적 개체 컬렉션을 업데이트합니다. 각 서적 개체에는 서적의 제목, 발행자, 가격 및 기타 데이터를 가져오고 설정하는 메서드가 들어 있습니다.

데모를 위해 호스트에서 서적 컬렉션을 만들고, 추가 기능은 모든 컴퓨터 서적의 가격을 20% 할인하고 모든 공포 서적을 컬렉션에서 제거합니다. 그런 다음 추가 기능은 베스트셀러 서적에 대한 새 서적 개체를 만들어 단일 개체로 호스트에 전달합니다.

이 연습에서는 다음 작업을 수행합니다.

  • Visual Studio 솔루션 만들기

  • 파이프라인 디렉터리 구조 만들기

  • 격리 경계 사이에 전달해야 하는 개체에 대한 계약 및 뷰 만들기

  • 격리 경계를 넘어 개체를 전달하는 데 필요한 추가 기능측 어댑터 및 호스트측 어댑터 만들기

  • 호스트 만들기

  • 추가 기능 만들기

  • 파이프라인 배포

  • 호스트 응용 프로그램 실행

참고참고

이 연습에 제공된 일부 코드에는 불필요한 네임스페이스 참조가 포함되어 있습니다.연습 단계에는 Visual Studio에 필요한 참조가 정확하게 반영됩니다.

추가 코드 샘플을 얻고 추가 기능 파이프라인 개발용 도구에 대한 고객 기술을 미리 보려면 CodePlex의 Managed Extensibility and Add-In Framework 사이트를 참조하십시오.

사전 요구 사항

이 연습을 완료하려면 다음 구성 요소가 필요합니다.

Visual Studio 솔루션 만들기

Visual Studio의 솔루션을 사용하여 파이프라인 세그먼트의 프로젝트를 포함할 수 있습니다.

파이프라인 솔루션을 만들려면

  1. Visual Studio에서 LibraryContracts라는 새 프로젝트를 만듭니다. 클래스 라이브러리 템플릿을 기반으로 합니다.

  2. 솔루션 이름을 BooksPipeline으로 지정합니다.

파이프라인 디렉터리 구조 만들기

추가 기능 모델에서는 파이프라인 세그먼트 어셈블리를 지정한 디렉터리 구조에 넣어야 합니다.

파이프라인 디렉터리 구조를 만들려면

  • 컴퓨터에 다음 폴더 구조를 만듭니다. Visual Studio 솔루션의 폴더 안을 비롯하여 아무 곳에나 이 폴더 구조를 배치할 수 있습니다.

    Pipeline
      AddIns
        BooksAddIn
      AddInSideAdapters
      AddInViews
      Contracts
      HostSideAdapters
    

    루트 폴더 이름과 개별 추가 기능 폴더의 이름을 제외한 모든 폴더 이름을 여기에 나와 있는 대로 정확하게 지정해야 합니다. 이 예제에서는 Pipeline을 루트 폴더 이름으로 사용하고 BooksAddIn을 추가 기능 폴더 이름으로 사용합니다.

    참고참고

    이 연습에서는 편의를 위해 호스트 응용 프로그램을 파이프라인 루트 폴더에 배치합니다.또한 호스트 응용 프로그램이 다른 위치에 포함되어 있는 경우 코드를 변경하는 방법을 설명하는 단계를 제공합니다.

    파이프라인 폴더 구조에 대한 자세한 내용은 파이프라인 개발 요구 사항을 참조하십시오.

계약 및 뷰 만들기

이 파이프라인의 계약 세그먼트에서는 다음 두 개의 인터페이스를 정의합니다.

  • IBookInfoContract 인터페이스

    이 인터페이스에는 서적에 대한 정보를 포함하는 Author 등의 메서드가 들어 있습니다.

  • ILibraryManagerContract 인터페이스

    이 인터페이스에는 추가 기능이 서적 컬렉션을 처리하는 데 사용하는 ProcessBooks 메서드가 들어 있습니다. 각 서적은 IBookInfoContract 계약을 나타냅니다. 또한 베스트셀러 서적을 나타내는 서적 개체를 호스트에 제공하기 위해 추가 기능에서 사용하는 GetBestSeller 메서드도 이 인터페이스에 포함되어 있습니다.

계약을 만들려면

  1. BooksPipeline이라는 Visual Studio 솔루션에서 LibraryContracts 프로젝트를 엽니다.

  2. Visual Basic에서는 LibraryContracts 프로젝트의 속성을 연 다음 응용 프로그램 탭을 사용하여 루트 네임스페이스에 지정된 기본값을 삭제합니다. 기본적으로 루트 네임스페이스는 프로젝트 이름으로 설정되어 있습니다.

  3. 솔루션 탐색기에서 다음 어셈블리에 대한 참조를 프로젝트에 추가합니다.

    Sytem.AddIn.Contract.dll

    System.AddIn.dll

  4. 클래스 파일에서 System.AddIn.ContractSystem.AddIn.Pipeline 네임스페이스에 대한 참조를 추가합니다.

  5. 클래스 파일에서 기본 클래스 선언을 다음과 같은 두 인터페이스로 바꿉니다.

    • ILibraryManagerContract 인터페이스. 추가 기능을 활성화하는 데 사용되므로 AddInContractAttribute 특성을 포함해야 합니다.

    • IBookInfoContract 인터페이스. 호스트와 추가 기능 간에 전달되는 개체를 나타내므로 특성이 필요하지 않습니다.

    두 인터페이스 모두 IContract 인터페이스를 상속해야 합니다.

  6. 다음 코드를 사용하여 IBookInfoContract 및 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();
        }
    }
    

추가 기능 뷰와 호스트 뷰의 코드가 같으므로 간단한 방법으로 동시에 뷰를 만들 수 있습니다. 단, 파이프라인의 이 세그먼트를 활성화하는 데 사용되는 추가 기능 뷰에는 AddInBaseAttribute 특성이 필요하고 호스트 뷰에는 특성이 필요하지 않다는 차이점이 있습니다.

이 파이프라인의 추가 기능 뷰에는 두 개의 추상 클래스가 있습니다. BookInfo 클래스는 IBookInfoContract 인터페이스에 대한 뷰를 제공하고 LibraryManager 클래스는 ILibraryManagerContract 인터페이스에 대한 뷰를 제공합니다.

추가 기능 뷰를 만들려면

  1. AddInViews라는 새 프로젝트를 BooksPipeline 솔루션에 추가합니다. 클래스 라이브러리 템플릿을 기반으로 합니다.

  2. Visual Basic에서는 프로젝트의 속성을 연 다음 응용 프로그램 탭을 사용하여 루트 네임스페이스에 지정된 기본값을 삭제합니다.

  3. 솔루션 탐색기에서 System.AddIn.dll에 대한 참조를 AddInViews 프로젝트에 추가합니다.

  4. 프로젝트의 기본 클래스인 LibraryManager의 이름을 바꾸고 클래스를 abstract(Visual Basic의 경우 MustInherit)로 설정합니다.

  5. 클래스 파일에서 System.AddIn.Pipeline 네임스페이스에 대한 참조를 추가합니다.

  6. LibraryManager 클래스는 파이프라인을 활성화하는 데 사용되므로 AddInBaseAttribute 특성을 적용해야 합니다.

  7. 다음 코드를 사용하여 LibraryManager 추상 클래스를 완료합니다.

    
    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. abstract 클래스(Visual Basic의 경우 MustInherit 클래스)를 프로젝트에 추가하고 클래스 이름을 BookInfo로 지정합니다. BookInfo 클래스는 호스트와 추가 기능 간에 전달되는 개체를 나타냅니다. 이 클래스는 파이프라인을 활성화하는 데 사용되지 않으므로 특성이 필요하지 않습니다.

  9. 다음 코드를 사용하여 BookInfo 추상 클래스를 완료합니다.

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

호스트 뷰를 만들려면

  1. HostViews라는 새 프로젝트를 BooksPipeline 솔루션에 추가합니다. 클래스 라이브러리 템플릿을 기반으로 합니다.

  2. Visual Basic에서는 프로젝트의 속성을 연 다음 응용 프로그램 탭을 사용하여 루트 네임스페이스에 지정된 기본값을 삭제합니다.

  3. 프로젝트의 기본 클래스인 LibraryManager의 이름을 바꾸고 클래스를 abstract(Visual Basic의 경우 MustInherit)로 설정합니다.

  4. 다음 코드를 사용하여 LibraryManager 추상 클래스를 완료합니다.

    
    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. abstract 클래스(Visual Basic의 경우 MustInherit 클래스)를 프로젝트에 추가하고 클래스 이름을 BookInfo로 지정합니다.

  6. 다음 코드를 사용하여 BookInfo 추상 클래스를 완료합니다.

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

추가 기능측 어댑터 만들기

이 파이프라인에 대한 추가 기능측 어댑터 어셈블리에는 다음 네 가지 어댑터 클래스가 들어 있습니다.

  • BookInfoContractToViewAddInAdapter

    이 어댑터는 호스트가 BookInfo 개체를 개별적으로 또는 컬렉션의 일부로 추가 기능에 전달할 때 호출됩니다. 이 클래스는 BookInfo 개체의 계약을 뷰로 변환합니다. 클래스는 추가 기능 뷰에서 상속되며 해당 클래스의 생성자로 전달되는 계약을 호출하여 뷰의 추상 메서드를 구현합니다.

    이 어댑터의 생성자는 계약을 받으므로 ContractHandle 개체를 계약에 적용하여 수명 관리를 구현할 수 있습니다.

    중요중요

    ContractHandle은 수명 관리에 필수적입니다.ContractHandle 개체에 대한 참조를 유지하지 못하는 경우 가비지 수집을 통해 이를 회수하게 되며 프로그램에서 더 이상 필요로 하지 않는 파이프라인은 종료됩니다.이로 인해 AppDomainUnloadedException 같이 진단하기 어려운 오류가 발생할 수 있습니다.종료는 파이프라인 수명의 정상적인 단계이므로 수명 관리 코드에서 이 상태가 오류인지 여부를 감지할 수는 없습니다.

  • BookInfoViewToContractAddInAdapter

    이 어댑터는 추가 기능이 BookInfo 개체를 호스트로 전달할 때 호출됩니다. 이 클래스는 BookInfo 개체의 추가 기능 뷰를 계약으로 변환합니다. 클래스는 계약에서 상속되며 해당 클래스의 생성자로 전달되는 추가 기능 뷰를 호출하여 계약을 구현합니다. 이 어댑터는 호스트에 계약으로 마샬링됩니다.

  • LibraryManagerViewToContractAddInAdapter

    추가 기능을 활성화하는 호출에서 호스트에 반환되는 형식입니다. 이 형식은 호스트 개체 컬렉션(IList<BookInfo>)을 추가 기능으로 전달하는 호출을 비롯하여 호스트가 추가 기능을 호출할 때 호출됩니다. 이 클래스는 ILibraryManagerContract 계약을 호스트 뷰 LibraryManager로 변환합니다. 이 클래스는 호스트 뷰에서 상속되며 해당 생성자에 전달되는 뷰를 호출하여 계약을 구현합니다.

    사용자 지정 형식 컬렉션인 BookInfo 개체가 격리 경계를 넘어서 마샬링되어야 하므로 이 어댑터는 CollectionAdapters 클래스를 사용합니다. 이 클래스는 IList<T> 컬렉션을 IListContract<T> 컬렉션으로 변환하는 메서드를 제공합니다. 그러면 격리 경계를 넘어서 컬렉션을 파이프라인 반대쪽으로 전달할 수 있습니다.

  • BookInfoAddInAdapter

    LibraryManagerViewToContractAddInAdapter 클래스에서 이 어댑터의 static 메서드(Visual Basic의 경우 Shared 메서드)를 호출하여 계약 또는 뷰를 적절하게 변경하거나 기존 계약 또는 뷰를 반환합니다. 이렇게 하면 개체가 호스트와 추가 기능 사이에서 라운드트립할 때 어댑터가 추가로 만들어지지 않습니다.

추가 기능측 어댑터를 만들려면

  1. AddInSideAdapters라는 새 프로젝트를 BooksPipeline 솔루션에 추가합니다. 클래스 라이브러리 템플릿을 기반으로 합니다.

  2. Visual Basic에서는 프로젝트의 속성을 연 다음 응용 프로그램 탭을 사용하여 루트 네임스페이스에 지정된 기본값을 삭제합니다.

  3. 솔루션 탐색기에서 다음 어셈블리에 대한 참조를 AddInSideAdapters 프로젝트에 추가합니다.

    System.AddIn.dll

    System.AddIn.Contract.dll

  4. 솔루션 탐색기에서 다음 프로젝트에 대한 참조를 AddInSideAdapters 프로젝트에 추가합니다.

    AddInViews

    LibraryContracts

    이러한 참조에 대해 참조 속성에서 로컬 복사False로 설정하여 참조된 어셈블리가 로컬 빌드 폴더에 복사되지 않게 합니다. 어셈블리는 이 연습의 뒷부분에 있는 "파이프라인 배포" 절차의 설명과 같이 파이프라인 디렉터리 구조에 배치됩니다.

  5. 클래스 파일의 이름을 BookInfoContractToViewAddInAdapter로 지정합니다.

  6. 클래스 파일에서 System.AddIn.Pipeline 네임스페이스에 대한 참조를 추가합니다.

  7. 다음 코드를 사용하여 BookInfoContractToViewAddInAdapter 클래스를 추가합니다. 이 클래스는 파이프라인을 활성화하는 데 사용되지 않으므로 특성이 필요 없습니다. internal(Visual Basic의 경우 Friend) GetSourceContract 메서드는 개체가 호스트와 추가 기능 사이에서 라운드트립할 때 어댑터가 추가로 만들어지지 않도록 하기 위해 BookInfoAddInAdapter 클래스에서 사용됩니다.

    
    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. 다음 코드를 사용하여 BookInfoViewToContractAddInAdapter 클래스를 AddInSideAdapters 프로젝트에 추가합니다. 이 클래스는 파이프라인을 활성화하는 데 사용되지 않으므로 특성이 필요 없습니다. internal(Visual Basic의 경우 Friend) GetSourceView 메서드는 개체가 호스트와 추가 기능 사이에서 라운드트립할 때 어댑터가 추가로 만들어지지 않도록 하기 위해 BookInfoAddInAdapter 클래스에서 사용됩니다.

    
    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. 다음 코드를 사용하여 LibraryManagerViewToContractAddInAdapter 클래스를 AddInSideAdapters 프로젝트에 추가합니다. 이 클래스는 파이프라인을 활성화하는 데 사용되므로 AddInAdapterAttribute 특성이 필요합니다.

    ProcessBooks 메서드는 격리 경계를 넘어 서적 목록을 전달하는 방법을 보여 줍니다. 이 메서드는 CollectionAdapters.ToIList 메서드를 사용하여 목록을 변환합니다. 또한 목록의 개체를 변환하기 위해 BookInfoAddInAdapter 클래스에서 제공하는 어댑터 메서드의 대리자를 전달합니다.

    GetBestSeller 메서드는 격리 경계를 넘어 단일 BookInfo 개체를 전달하는 방법을 보여 줍니다.

    
    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. 다음 코드를 사용하여 BookInfoAddInAdapter 클래스를 AddInSideAdapters 프로젝트에 추가합니다. 이 클래스에는 ContractToViewAdapter와 ViewToContractAdapter라는 두 개의 static 메서드(Visual Basic의 경우 Shared 메서드)가 포함되어 있습니다. 이러한 메서드는 다른 어댑터 클래스에서만 사용되므로 internal(Visual Basic의 경우 Friend)입니다. 이러한 메서드는 개체가 호스트와 추가 기능 사이에서 라운드트립할 때 어댑터가 추가로 만들어지지 않게 하는 데 사용됩니다. 격리 경계를 넘어 개체를 전달하는 어댑터에 이러한 메서드를 제공해야 합니다.

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

호스트측 어댑터 만들기

이 파이프라인에 대한 호스트측 어댑터 어셈블리에는 다음 네 가지 어댑터 클래스가 들어 있습니다.

  • BookInfoContractToViewHostAdapter

    이 어댑터는 추가 기능이 BookInfo 개체를 개별적으로 또는 컬렉션의 일부로 호스트에 전달할 때 호출됩니다. 이 클래스는 BookInfo 개체의 계약을 뷰로 변환합니다. 클래스는 호스트 뷰에서 상속되며 해당 클래스의 생성자로 전달되는 계약을 호출하여 뷰의 추상 메서드를 구현합니다.

    이 어댑터의 생성자는 계약을 받으므로 ContractHandle 개체를 계약에 적용하여 수명 관리를 구현할 수 있습니다.

    중요중요

    ContractHandle은 수명 관리에 필수적입니다.ContractHandle 개체에 대한 참조를 유지하지 못하는 경우 가비지 수집을 통해 이를 회수하게 되며 프로그램에서 더 이상 필요로 하지 않는 파이프라인은 종료됩니다.이로 인해 AppDomainUnloadedException 같이 진단하기 어려운 오류가 발생할 수 있습니다.종료는 파이프라인 수명의 정상적인 단계이므로 수명 관리 코드에서 이 상태가 오류인지 여부를 감지할 수는 없습니다.

  • BookInfoViewToContractHostAdapter

    이 어댑터는 호스트가 BookInfo 개체를 추가 기능으로 전달할 때 호출됩니다. 이 클래스는 BookInfo 개체의 호스트 뷰를 계약으로 변환합니다. 클래스는 계약에서 상속되며 해당 클래스의 생성자로 전달되는 추가 기능 뷰를 호출하여 계약을 구현합니다. 이 어댑터는 추가 기능에 계약으로 마샬링됩니다.

  • LibraryManagerContractToViewHostAdapter

    이 어댑터는 호스트가 BookInfo 개체 컬렉션을 추가 기능으로 전달할 때 호출됩니다. 추가 기능은 이 컬렉션에 대해 ProcessBooks 메서드 구현을 수행합니다.

    이 클래스는 LibraryManager 개체의 호스트 뷰를 계약으로 변환합니다. 이 클래스는 계약에서 상속되며 클래스 생성자로 전달되는 호스트 뷰를 호출하여 계약을 구현합니다.

    사용자 지정 형식 컬렉션인 BookInfo 개체가 격리 경계를 넘어서 마샬링되어야 하므로 이 어댑터는 CollectionAdapters 클래스를 사용합니다. 이 클래스는 IList<T> 컬렉션을 IListContract<T> 컬렉션으로 변환하는 메서드를 제공합니다. 그러면 격리 경계를 넘어서 컬렉션을 파이프라인 반대쪽으로 전달할 수 있습니다.

  • BookInfoHostAdapter

    이 어댑터는 LibraryManagerViewToContractHostAdapter 클래스에서 호출되어 호출에 대한 새 인스턴스를 만드는 대신 조정을 위해 기존 계약 또는 뷰를 반환합니다. 이렇게 하면 개체가 호스트와 추가 기능 사이에서 라운드트립할 때 어댑터가 추가로 만들어지지 않습니다.

호스트측 어댑터를 만들려면

  1. HostSideAdapters라는 새 프로젝트를 BooksPipeline 솔루션에 추가합니다. 클래스 라이브러리 템플릿을 기반으로 합니다.

  2. Visual Basic에서는 프로젝트의 속성을 연 다음 응용 프로그램 탭을 사용하여 루트 네임스페이스에 지정된 기본값을 삭제합니다.

  3. 솔루션 탐색기에서 다음 어셈블리에 대한 참조를 HostSideAdapters 프로젝트에 추가합니다.

    System.AddIn.dll

    System.AddIn.Contract.dll

  4. 솔루션 탐색기에서 다음 프로젝트에 대한 참조를 HostSideAdapters 프로젝트에 추가합니다.

    HostViews

    LibraryContracts

    이러한 참조에 대해 참조 속성에서 로컬 복사False로 설정하여 참조된 어셈블리가 로컬 빌드 폴더에 복사되지 않게 합니다.

  5. 클래스 파일에서 System.AddIn.Pipeline 네임스페이스에 대한 참조를 추가합니다.

  6. 다음 코드를 사용하여 BookInfoContractToViewHostAdapter 클래스를 추가합니다. 이 클래스는 파이프라인을 활성화하는 데 사용되지 않으므로 특성이 필요 없습니다. internal(Visual Basic의 경우 Friend) GetSourceContract 메서드는 개체가 호스트와 추가 기능 사이에서 라운드트립할 때 어댑터가 추가로 만들어지지 않도록 하기 위해 BookInfoAddInAdapter 클래스에서 사용됩니다.

    
    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. 다음 코드를 사용하여 BookInfoViewToContractHostAdapter를 HostSideAdapters 프로젝트에 추가합니다. 이 클래스는 파이프라인을 활성화하는 데 사용되지 않으므로 특성이 필요 없습니다. internal(Visual Basic의 경우 Friend) GetSourceView 메서드는 개체가 호스트와 추가 기능 사이에서 라운드트립할 때 어댑터가 추가로 만들어지지 않도록 하기 위해 BookInfoAddInAdapter 클래스에서 사용됩니다.

    
    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. 다음 코드를 사용하여 LibraryManagerContractToViewHostAdapter를 HostSideAdapters 프로젝트에 추가합니다. 이 클래스는 파이프라인을 활성화하는 데 사용되므로 HostAdapterAttribute 특성이 필요합니다.

    ProcessBooks 메서드는 격리 경계를 넘어 서적 목록을 전달하는 방법을 보여 줍니다. 이 메서드는 CollectionAdapters.ToIListContract 메서드를 사용하여 목록을 변환합니다. 또한 목록의 개체를 변환하기 위해 BookInfoHostAdapter 클래스에서 제공하는 어댑터 메서드의 대리자를 전달합니다.

    GetBestSeller 메서드는 격리 경계를 넘어 단일 BookInfo 개체를 전달하는 방법을 보여 줍니다.

    
    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. 다음 코드를 사용하여 BookInfoHostAdapter 클래스를 HostSideAdapters 프로젝트에 추가합니다. 이 클래스에는 ContractToViewAdapter와 ViewToContractAdapter라는 두 개의 static 메서드(Visual Basic의 경우 Shared 메서드)가 포함되어 있습니다. 이러한 메서드는 다른 어댑터 클래스에서만 사용되므로 internal(Visual Basic의 경우 Friend)입니다. 이러한 메서드는 개체가 호스트와 추가 기능 사이에서 라운드트립할 때 어댑터가 추가로 만들어지지 않게 하는 데 사용됩니다. 격리 경계를 넘어 개체를 전달하는 어댑터에 이러한 메서드를 제공해야 합니다.

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

호스트 만들기

호스트 응용 프로그램은 호스트 뷰를 통해 추가 기능과 상호 작용합니다. AddInStoreAddInToken 클래스에서 제공하는 추가 기능 검색 및 활성화 메서드를 사용하여 다음을 수행합니다.

  • 파이프라인 및 추가 기능 정보의 캐시를 다시 빌드합니다.

  • 지정한 파이프라인 루트 디렉터리에서 LibraryManager 형식의 추가 기능을 찾습니다.

  • 사용할 추가 기능을 선택하라는 메시지를 사용자에게 표시합니다. 이 예제에서는 하나의 추가 기능만 사용할 수 있습니다.

  • 새 응용 프로그램 도메인에서 지정된 보안 신뢰 수준으로 선택한 추가 기능을 활성화합니다.

  • ProcessBooks 메서드를 호출하여 BookInfo 개체 컬렉션을 추가 기능으로 전달합니다. 추가 기능은 ProcessBooks 메서드의 구현을 호출하고 컴퓨터 서적 20% 할인 등의 함수를 수행합니다.

  • 베스트셀러 서적에 대한 정보가 포함된 BookInfo 개체를 반환하기 위해 추가 기능에서 사용하는 GetBestSeller 메서드를 호출합니다.

  • Data 메서드를 호출하여 추가 기능에서 현재 판매세율을 가져옵니다. 이 메서드는 serialize 가능한 봉인 참조 형식인 문자열을 사용하고 반환합니다. 따라서 뷰에서 계약으로 변환하는 어댑터 및 계약에서 뷰로 변환하는 어댑터를 사용하지 않고도 격리 경계를 넘어서 파이프라인의 반대쪽으로 메서드를 전달할 수 있습니다.

호스트에는 BookInfo 개체 컬렉션을 만드는 CreateBooks 메서드가 있습니다. 이 메서드는 Sample XML File (books.xml)에 있는 books.xml 샘플 파일을 사용하여 컬렉션을 만듭니다.

호스트를 만들려면

  1. BookStore라는 새 프로젝트를 BooksPipeline 솔루션에 추가합니다. 콘솔 응용 프로그램 템플릿을 기반으로 합니다.

  2. Visual Basic에서는 프로젝트의 속성을 연 다음 응용 프로그램 탭을 사용하여 루트 네임스페이스에 지정된 기본값을 삭제합니다.

  3. 솔루션 탐색기에서 System.AddIn.dll 어셈블리에 대한 참조를 BookStore 프로젝트에 추가합니다.

  4. 프로젝트 참조를 HostViews 프로젝트에 추가합니다. 이 참조에 대해 참조 속성에서 로컬 복사False로 설정하여 참조된 어셈블리가 로컬 빌드 폴더에 복사되지 않게 합니다.

  5. Visual Basic에서는 다음과 같이 모듈을 클래스로 변경합니다.

    • 프로젝트에서 기본 모듈을 제외하고 Program 클래스를 추가합니다.

    • Public 키워드를 Friend 키워드로 바꿉니다.

    • 클래스에 Shared Sub Main() 프로시저를 추가합니다.

    • 프로젝트 속성 대화 상자의 응용 프로그램 탭을 사용하여 시작 개체Sub Main으로 설정합니다.

  6. 클래스 파일에서 System.AddIn.Pipeline 및 호스트 뷰 세그먼트 네임스페이스에 대한 참조를 추가합니다.

  7. 솔루션 탐색기에서 솔루션을 선택하고 프로젝트 메뉴에서 속성을 선택한 다음, 솔루션 속성 페이지 대화 상자에서 한 개의 시작 프로젝트를 이 호스트 응용 프로그램 프로젝트로 설정합니다.

  8. 호스트 응용 프로그램에 대해 다음 코드를 사용합니다.

    참고참고

    books.xml 파일이 응용 프로그램 폴더에서 로드되도록 코드에서 이 파일이 로드되는 위치를 "books.xml"로 변경하십시오.응용 프로그램을 Pipeline 폴더 이외의 다른 위치에 배치하려는 경우에는 addInRoot 변수에 파이프라인 디렉터리 구조의 경로가 포함되도록 이 변수를 설정하는 코드 줄을 변경해야 합니다.

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

books.xml 데이터 파일을 만들려면

  1. BookStore 프로젝트에 새 XML 파일을 추가합니다. 새 항목 추가 대화 상자가 나타나면 파일 이름을 books.xml로 지정합니다.

  2. books.xml의 기본 콘텐츠를 Sample XML File (books.xml)의 XML로 바꿉니다.

  3. 솔루션 탐색기에서 books.xml을 선택하고 속성에서 출력 디렉터리로 복사항상 복사로 설정합니다.

추가 기능 만들기

추가 기능은 추가 기능 뷰에서 지정한 메서드를 구현합니다. 이 추가 기능은 ProcessBooks 메서드를 구현합니다. 이 메서드는 호스트에서 전달하는 BookInfo 개체 컬렉션에 대해 다음 작업을 수행합니다.

  • 모든 컴퓨터 서적의 가격을 20% 할인합니다.

  • 모든 공포 서적을 컬렉션에서 제거합니다.

또한 이 추가 기능은 베스트셀러 서적에 대해 설명하는 BookInfo 개체를 호스트에 전달하여 GetBestSeller 메서드를 구현합니다.

추가 기능을 만들려면

  1. BooksAddin이라는 새 프로젝트를 BooksPipeline 솔루션에 추가합니다. 클래스 라이브러리 템플릿을 기반으로 합니다.

  2. Visual Basic에서는 프로젝트의 속성을 연 다음 응용 프로그램 탭을 사용하여 루트 네임스페이스에 지정된 기본값을 삭제합니다.

  3. 솔루션 탐색기에서 System.AddIn.dll 어셈블리에 대한 참조를 BooksAddin 프로젝트에 추가합니다.

  4. AddInViews 프로젝트에 프로젝트 참조를 추가합니다. 이 참조에 대해 참조 속성에서 로컬 복사False로 설정하여 참조된 어셈블리가 로컬 빌드 폴더에 복사되지 않게 합니다.

  5. 클래스 파일에서 System.AddIn 및 추가 기능 뷰 세그먼트 네임스페이스에 대한 참조를 추가합니다.

  6. 추가 기능 응용 프로그램에 대해 다음 코드를 사용합니다.

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

파이프라인 배포

이제 추가 기능 세그먼트를 빌드하고 필요한 파이프라인 디렉터리 구조에 배포할 준비가 되었습니다.

세그먼트를 파이프라인에 배포하려면

  1. 솔루션의 각 프로젝트에 대해 프로젝트 속성빌드 탭(Visual Basic의 경우 컴파일 탭)을 사용하여 다음 표와 같이 출력 경로(Visual Basic의 경우 빌드 출력 경로) 값을 설정합니다.

    프로젝트

    경로

    BooksAddIn

    Pipeline\AddIns\CalcV1

    AddInSideAdapters

    Pipeline\AddInSideAdapters

    AddInViews

    Pipeline\AddInViews

    LibraryContracts

    Pipeline\Contracts

    BookStore

    Pipeline 또는 사용자가 정의한 응용 프로그램 디렉터리

    HostSideAdapters

    Pipeline\HostSideAdapters

    HostViews

    Pipeline 또는 사용자가 정의한 응용 프로그램 디렉터리

    참고참고

    응용 프로그램을 Pipeline 폴더 이외의 다른 위치에 추가하려면 파이프라인 루트 디렉터리 위치를 지정하는 호스트 코드를 변경해야 합니다.

  2. Visual Studio 솔루션을 빌드합니다.

    파이프라인에 배포하는 방법에 대한 자세한 내용은 파이프라인 개발 요구 사항을 참조하십시오.

호스트 응용 프로그램 실행

이제 호스트를 실행하고 추가 기능과 상호 작용할 준비가 되었습니다.

호스트 응용 프로그램을 실행하려면

  1. 명령 프롬프트에서 파이프라인 루트 디렉터리로 이동하여 호스트 응용 프로그램을 실행합니다. 이 예제에서 호스트 응용 프로그램은 BookStore.exe입니다.

  2. 호스트는 해당 형식의 사용 가능한 모든 추가 기능을 찾고 추가 기능을 선택하라는 메시지를 표시합니다. 사용 가능한 추가 기능이 하나뿐이면 1을 입력합니다.

    호스트에서 추가 기능을 활성화한 후 사용하여 서적 목록에 대해 몇 가지 작업을 수행합니다.

  3. 아무 키나 눌러 응용 프로그램을 닫습니다.

참고 항목

작업

연습: 확장 가능한 응용 프로그램 만들기

연습: 호스트 변경으로 인한 이전 버전과의 호환성 활성화

개념

파이프라인 개발 요구 사항

계약, 뷰 및 어댑터

파이프라인 개발