共用方式為


逐步解說:建立可延伸應用程式

更新: 2008 年 7 月

本逐步解說將說明如何建立增益集的管線,這個增益集會執行簡單的計算機功能。本逐步解說不會示範實際狀況的案例,而是示範管線的基本功能,以及增益集如何為主應用程式 (Host) 提供服務。

本逐步解說將說明下列工作:

  • 建立 Visual Studio 方案。

  • 建立管線目錄結構。

  • 建立合約和檢視。

  • 建立增益集端配接器。

  • 建立主應用程式端配接器。

  • 建立主應用程式。

  • 建立增益集。

  • 部署管線。

  • 執行主應用程式。

這個管線只會在主應用程式和增益集之間傳遞可序列化的型別 (DoubleString)。如需示範如何傳遞複雜資料型別之集合的範例,請參閱逐步解說:在主應用程式和增益集之間傳遞集合

此管線的合約定義了四個數學運算的物件模型:加法、減法、乘法和除法。主應用程式會為增益集提供方程式進行計算 (例如 2 + 2),然後增益集再將結果傳回主應用程式。

計算機增益集的第 2 版提供了更多計算的可能性,並示範了版本控制。這些部分將在逐步解說:在主應用程式變更時確保回溯相容性中加以說明。

注意事項:

您可以在 CodePlex 上的 Managed 擴充性及增益集架構網站 (英文) 找到更多範例程式碼,以及可用來建置增益集管線之工具的客戶技術預覽。

必要條件

您需要下列項目才能完成本逐步解說:

  • Visual Studio

建立 Visual Studio 方案

您可以使用 Visual Studio 內的方案來包含管線區段的專案。

若要建立管線方案

  1. 在 Visual Studio 中,建立名為 Calc1Contract 的新專案。以 [類別庫] 範本為基礎。

  2. 將方案命名為 CalculatorV1。

建立管線目錄結構

增益集模型需要將管線區段組件放置在指定的目錄結構中。如需管線結構的詳細資訊,請參閱管線開發需求

若要建立管線目錄結構

  1. 在電腦上任何地方建立應用程式資料夾。

  2. 在該資料夾中,建立下列結構:

    Pipeline
      AddIns
        CalcV1
        CalcV2
      AddInSideAdapters
      AddInViews
      Contracts
      HostSideAdapters
    

    管線資料夾結構並不一定要放置在應用程式資料夾中,在這裡只是為了方便而這麼做。本逐步解說會在適當的步驟中,說明在管線資料夾結構位於其他位置時要如何變更程式碼。請參閱管線開發需求中有關管線目錄需求的討論。

    注意事項:

    本逐步解說中不會使用 CalcV2 資料夾,這是逐步解說:在主應用程式變更時確保回溯相容性的預留位置。

建立合約和檢視

這個管線的合約區段會定義 ICalc1Contract 介面,這個介面會定義四個方法:add、subtract、multiply 和 divide。

若要建立合約

  1. 在名為 CalculatorV1 的 Visual Studio 方案中,開啟 Calc1Contract 專案。

  2. 在 [方案總管] 中,將下列組件的參考加入至 Calc1Contract 專案:

    System.AddIn.Contract.dll

    System.AddIn.dll

  3. 在 [方案總管] 中,排除加入至新 [類別庫] 專案的預設類別。

  4. 在 [方案總管] 中,使用 [介面] 範本在專案中加入新項目。在 [加入新項目] 對話方塊中,將介面命名為 ICalc1Contract。

  5. 在介面檔 (Interface File) 中,加入 System.AddIn.ContractSystem.AddIn.Pipeline 的命名空間參考。

  6. 使用下列程式碼完成這個合約區段。請注意,這個介面必須有 AddInContractAttribute 屬性。

    Imports System.AddIn.Contract
    Imports System.AddIn.Pipeline
    
    Namespace CalculatorContracts
    
        ' The AddInContractAttribute identifes this pipeline segment as a
        ' contract.
        <AddInContract()> _
        Public Interface ICalc1Contract
            Inherits IContract
    
            Function Add(ByVal a As Double, ByVal b As Double) As Double
            Function Subtract(ByVal a As Double, ByVal b As Double) As Double
            Function Multiply(ByVal a As Double, ByVal b As Double) As Double
            Function Divide(ByVal a As Double, ByVal b As Double) As Double
        End Interface
    
    End Namespace
    
    using System.AddIn.Contract;
    using System.AddIn.Pipeline;
    
    namespace CalculatorContracts
    {
        // The AddInContractAttribute identifes this pipeline segment as a 
        // contract.
        [AddInContract]
        public interface ICalc1Contract : IContract
        {
        double Add(double a, double b);
        double Subtract(double a, double b);
        double Multiply(double a, double b);
        double Divide(double a, double b);
        }
    }
    
  7. 您可以選擇性的建置 Visual Studio 方案。方案必須在最後的程序才能執行,但在每個程序後建置方案可以確保每個專案都正確無誤。

由於增益集檢視和增益集的主應用程式檢視通常具有相同的程式碼,特別是在增益集的第一個版本中,所以您可以輕鬆地在同一時間建立這些檢視。其中唯一不同的一個因素是:增益集檢視需要 AddInBaseAttribute 屬性,但增益集的主應用程式檢視則不需要任何屬性。

若要建立增益集檢視

  1. 將名為 Calc1AddInView 的新專案加入至 CalculatorV1 方案。以 [類別庫] 範本為基礎。

  2. 在 [方案總管] 中,將 System.AddIn.dll 的參考加入至 Calc1AddInView 專案。

  3. 在 [方案總管] 中,排除加入至新 [類別庫] 專案的預設類別,並使用 [介面] 範本在專案中加入新項目。在 [加入新項目] 對話方塊中,將介面命名為 ICalculator。

  4. 在介面檔中,加入 System.AddIn.Pipeline 的命名空間參考。

  5. 使用下列程式碼完成這個增益集檢視。請注意,這個介面必須有 AddInBaseAttribute 屬性。

    Imports System.AddIn.Pipeline
    
    Namespace CalcAddInViews
    
        ' The AddInBaseAttribute identifes this interface as the basis for the
        ' add-in view pipeline segment.
        <AddInBaseAttribute()> _
        Public Interface ICalculator
    
            Function Add(ByVal a As Double, ByVal b As Double) As Double
            Function Subtract(ByVal a As Double, ByVal b As Double) As Double
            Function Multiply(ByVal a As Double, ByVal b As Double) As Double
            Function Divide(ByVal a As Double, ByVal b As Double) As Double
        End Interface
    
    End Namespace
    
    using System.AddIn.Pipeline;
    
    namespace CalcAddInViews 
    {
        // The AddInBaseAttribute identifes this interface as the basis for
        // the add-in view pipeline segment.
        [AddInBase()]
        public interface ICalculator 
        {
        double Add(double a, double b);
        double Subtract(double a, double b);
        double Multiply(double a, double b);
        double Divide(double a, double b);
        }
    }
    
  6. 您可以選擇性的建置 Visual Studio 方案。

若要建立增益集的主應用程式檢視

  1. 將名為 Calc1HVA 的新專案加入至 CalculatorV1 方案。以 [類別庫] 範本為基礎。

  2. 在 [方案總管] 中,排除加入至新 [類別庫] 專案的預設類別,並使用 [介面] 範本在專案中加入新項目。在 [加入新項目] 對話方塊中,將介面命名為 ICalculator。

  3. 在介面檔中,使用下列程式碼完成增益集的主應用程式檢視。

    Namespace CalcHVAs
    
        Public Interface ICalculator
            Function Add(ByVal a As Double, ByVal b As Double) As Double
            Function Subtract(ByVal a As Double, ByVal b As Double) As Double
            Function Multiply(ByVal a As Double, ByVal b As Double) As Double
            Function Divide(ByVal a As Double, ByVal b As Double) As Double
        End Interface
    
    End Namespace
    
    namespace CalcHVAs 
    {
        public interface ICalculator 
        {
            double Add(double a, double b);
            double Subtract(double a, double b);
            double Multiply(double a, double b);
            double Divide(double a, double b);
        }
    }
    
  4. 您可以選擇性的建置 Visual Studio 方案。

建立增益集端配接器

這個增益集端配接器是由一個檢視至合約配接器所組成。這個管線區段會將型別從增益集檢視轉換為合約。

在本管線中,增益集提供主應用程式服務,型別也會從增益集移往主應用程式。由於沒有型別從主應用程式移往增益集,所以您不需要在這個管線的增益集端包含合約至檢視的配接器。

若要建立增益集端配接器

  1. 將名為 Calc1AddInSideAdapter 的新專案加入至 CalculatorV1 方案。以 [類別庫] 範本為基礎。

  2. 在 [方案總管] 中,將下列組件的參考加入至 Calc1AddInSideAdapter 專案:

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. 將專案參考加入至相鄰管線區段的專案:

    Calc1AddInView

    Calc1Contract

  4. 選取每個專案參考,然後在 [屬性] 中,將 [複製到本機] 設定為 [False]。在 Visual Basic 中,使用 [專案屬性] 的 [參考] 索引標籤,將兩個專案參考的 [複製到本機] 設定為 [False]。

  5. 重新命名專案的預設類別 CalculatorViewToContractAddInSideAdapter。

  6. 在類別檔案中,加入 System.AddIn.Pipeline 的命名空間參考。

  7. 在類別檔案中,加入相鄰區段的命名空間參考:CalcAddInViews 和 CalculatorContracts (除非您關閉了 Visual Basic 專案中的預設命名空間,否則在 Visual Basic 中,這些命名空間參考為 Calc1AddInView.CalcAddInViews 和 Calc1Contract.CalculatorContracts)。

  8. 套用 AddInAdapterAttribute 屬性至 CalculatorViewToContractAddInSideAdapter 類別,以識別做為增益集端配接器。

  9. 讓 CalculatorViewToContractAddInSideAdapter 類別繼承 ContractBase,該基底類別提供 IContract 介面的預設實作,並實作管線 ICalc1Contract 的合約介面。

  10. 加入公用建構函式,以接受 ICalculator、快取至私用欄位並呼叫基底類別建構函式。

  11. 若要實作 ICalc1Contract 的成員,只要呼叫傳遞到建構函式的 ICalculator 執行個體的對應成員,並傳回結果。這樣可以讓檢視 (ICalculator) 適用於合約 (ICalc1Contract)。

    下列程式碼示範完整的增益集端配接器。

    Imports System.AddIn.Pipeline
    Imports Calc1AddInView.CalcAddInViews
    Imports Calc1Contract.CalculatorContracts
    
    Namespace CalcAddInSideAdapters
    
        ' The AddInAdapterAttribute identifes this class as the add-in-side 
        ' adapter pipeline segment.
        <AddInAdapter()> _
        Public Class CalculatorViewToContractAddInSideAdapter
            Inherits ContractBase
            Implements ICalc1Contract
    
            Private _view As ICalculator
    
            Public Sub New(ByVal view As ICalculator)
                MyBase.New()
                _view = view
            End Sub
    
            Public Function Add(ByVal a As Double, ByVal b As Double) As Double Implements ICalc1Contract.Add
                Return _view.Add(a, b)
            End Function
    
            Public Function Subtract(ByVal a As Double, ByVal b As Double) As Double Implements ICalc1Contract.Subtract
                Return _view.Subtract(a, b)
            End Function
    
            Public Function Multiply(ByVal a As Double, ByVal b As Double) As Double Implements ICalc1Contract.Multiply
                Return _view.Multiply(a, b)
            End Function
    
            Public Function Divide(ByVal a As Double, ByVal b As Double) As Double Implements ICalc1Contract.Divide
                Return _view.Divide(a, b)
            End Function
    
        End Class
    End Namespace
    
    using System.AddIn.Pipeline;
    using CalcAddInViews;
    using CalculatorContracts;
    
    namespace CalcAddInSideAdapters 
    {
        // The AddInAdapterAttribute identifes this class as the add-in-side adapter
        // pipeline segment.
        [AddInAdapter()]
        public class CalculatorViewToContractAddInSideAdapter :
            ContractBase, ICalc1Contract 
        {
            private ICalculator _view;
    
            public CalculatorViewToContractAddInSideAdapter(ICalculator view) 
            {
                _view = view;
            }
    
            public virtual double Add(double a, double b) 
            {
                return _view.Add(a, b);
            }
    
            public virtual double Subtract(double a, double b) 
            {
                return _view.Subtract(a, b);
            }
    
            public virtual double Multiply(double a, double b) 
            {
                return _view.Multiply(a, b);
            }
    
            public virtual double Divide(double a, double b) 
            {
                return _view.Divide(a, b);
            }
        }
    }
    
  12. 您可以選擇性的建置 Visual Studio 方案。

建立主應用程式端配接器

這個主應用程式端配接器是由一個合約至檢視配接器所組成。這個區段可以讓合約適用於增益集的主應用程式檢視。

在本管線中,增益集提供主應用程式服務,型別也會從增益集移往主應用程式。由於沒有型別從主應用程式移往增益集,您不需要包含檢視至合約的配接器。

若要實作存留期管理,請使用 ContractHandle 物件,將存留期語彙基元附加至合約。您必須保留此控制代碼的參考,存留期管理才會運作。套用語彙基元 (Token) 後便不需要進行其他的程式設計,因為增益集系統可以在不再使用物件時處置 (Dispose) 那些物件,並使其可供記憶體回收使用。如需詳細資訊,請參閱存留期管理

若要建立主應用程式端配接器

  1. 將名為 Calc1HostSideAdapter 的新專案加入至 CalculatorV1 方案。以 [類別庫] 範本為基礎。

  2. 在 [方案總管] 中,將下列組件的參考加入至 Calc1HostSideAdapter 專案:

    System.AddIn.dll

    System.AddIn.Contract.dll

  3. 將專案參考加入至鄰近區段的專案:

    Calc1Contract

    Calc1HVA

  4. 選取每個專案參考,然後在 [屬性] 中,將 [複製到本機] 設定為 [False]。在 Visual Basic 中,使用 [專案屬性] 的 [參考] 索引標籤,將兩個專案參考的 [複製到本機] 設定為 [False]。

  5. 重新命名專案的預設類別 CalculatorContractToViewHostSideAdapter。

  6. 在類別檔案中,加入 System.AddIn.Pipeline 的命名空間參考。

  7. 在類別檔案中,加入相鄰區段的命名空間參考:CalcHVAs 和 CalculatorContracts (除非您關閉了 Visual Basic 專案中的預設命名空間,否則在 Visual Basic 中,這些命名空間參考為 Calc1HVA.CalcHVAs 和 Calc1Contract.CalculatorContracts)。

  8. 套用 HostAdapterAttribute 屬性至 CalculatorContractToViewHostSideAdapter 類別,以識別做為主應用程式端配接器區段。

  9. 讓 CalculatorContractToViewHostSideAdapter 類別實作代表增益集的主應用程式檢視:Calc1HVAs.ICalculator (Visual Basic 中的 Calc1HVA.CalcHVAs.ICalculator)。

  10. 加入公用建構函式,以接受管線合約類型 ICalc1Contract。建構函式必須快取合約參考,也必須建立並快取合約的新 ContractHandle,以管理增益集的存留期。

    重要事項:

    ContractHandle 對於存留期管理來說非常重要。如果您無法保留 ContractHandle 物件的參考,記憶體回收將會回收該物件,而且若程式不接受管線,管線將隨即關閉。這可能會造成難以診斷的錯誤,例如 AppDomainUnloadedException。關機是管線週期的正常階段,因此存留期管理程式碼無法將這種狀況偵測為錯誤。

  11. 若要實作 ICalculator 的成員,只要呼叫傳遞到建構函式的 ICalc1Contract 執行個體的對應成員,並傳回結果。這樣可以讓合約 (ICalc1Contract) 適用於檢視 (ICalculator)。

    下列程式碼示範完整的主應用程式端配接器。

    Imports System.AddIn.Pipeline
    Imports Calc1Contract.CalculatorContracts
    Imports Calc1HVA.CalcHVAs
    
    Namespace CalcHostSideAdapters
    
        ' The HostAdapterAttribute identifes this class as the host-side adapter
        ' pipeline segment.
        <HostAdapterAttribute()> _
        Public Class CalculatorContractToViewHostSideAdapter
            Implements ICalculator
    
            Private _contract As ICalc1Contract
            Private _handle As System.AddIn.Pipeline.ContractHandle
    
            Public Sub New(ByVal contract As ICalc1Contract)
                    MyBase.New()
                _contract = contract
                _handle = New ContractHandle(contract)
            End Sub
    
            Public Function Add(ByVal a As Double, ByVal b As Double) As Double _
                    Implements ICalculator.Add
                Return _contract.Add(a, b)
            End Function
    
            Public Function Subtract(ByVal a As Double, ByVal b As Double) As Double _
                    Implements ICalculator.Subtract
                Return _contract.Subtract(a, b)
            End Function
    
            Public Function Multiply(ByVal a As Double, ByVal b As Double) As Double _
                    Implements ICalculator.Multiply
                Return _contract.Multiply(a, b)
            End Function
    
            Public Function Divide(ByVal a As Double, ByVal b As Double) As Double _
                    Implements ICalculator.Divide
                Return _contract.Divide(a, b)
            End Function
    
        End Class
    
    End Namespace
    
    using System.AddIn.Pipeline;
    using CalcHVAs;
    using CalculatorContracts;
    
    namespace CalcHostSideAdapters 
    {
        // The HostAdapterAttribute identifes this class as the host-side adapter
        // pipeline segment.
        [HostAdapterAttribute()]
        public class CalculatorContractToViewHostSideAdapter : ICalculator 
        {
            private ICalc1Contract _contract;
            private System.AddIn.Pipeline.ContractHandle _handle;
    
            public CalculatorContractToViewHostSideAdapter(ICalc1Contract contract) 
            {
                _contract = contract;
                _handle = new ContractHandle(contract);
            }
    
            public double Add(double a, double b) 
            {
                return _contract.Add(a, b);
            }
    
            public double Subtract(double a, double b) 
            {
                return _contract.Subtract(a, b);
            }
    
            public double Multiply(double a, double b) 
            {
                return _contract.Multiply(a, b);
            }
    
            public double Divide(double a, double b) 
            {
                return _contract.Divide(a, b);
            }
        }
    }
    
  12. 您可以選擇性的建置 Visual Studio 方案。

建立主應用程式

主應用程式 (Host Application) 會透過增益集的主應用程式檢視與增益集互動。它會使用 AddInStoreAddInToken 類別所提供的增益集探索 (Discovery) 和啟動方法,以執行下列動作:

  • 更新管線的快取和增益集資訊。

  • 在指定的管線根目錄下,找出主應用程式檢視型別 ICalculator 的增益集。

  • 提示使用者指定要使用的增益集。

  • 以指定的安全信任層級,啟動新的應用程式定義域中選取的增益集。

  • 執行自訂的 RunCalculator 方法,這會呼叫由增益集的主應用程式檢視所指定之增益集的方法。

若要建立主應用程式

  1. 將名為 Calc1Host 的新專案加入至 CalculatorV1 方案。以 [主控台應用程式] 範本為基礎。

  2. 在 [方案總管] 中,將 System.AddIn.dll 組件的參考加入至 Calc1Host 專案。

  3. 在 Calc1HVA 專案中加入專案參考。選取專案參考,然後在 [屬性] 中,將 [複製到本機] 設定為 [False]。在 Visual Basic 中,使用 [專案屬性] 的 [參考] 索引標籤,將 [複製到本機] 設定為 [False]。

  4. 重新命名類別檔案 (Visual Basic 中的模組) MathHost1。

  5. 在 Visual Basic 中,使用 [專案屬性] 對話方塊的 [應用程式] 索引標籤,將 [啟始物件] 設定為 [Sub Main]。

  6. 在類別或模組檔案中,加入 System.AddIn.Hosting 的命名空間參考。

  7. 在類別或模組檔案中,加入增益集主應用程式檢視的命名空間參考:CalcHVAs (除非您關閉了 Visual Basic 專案中的預設命名空間,否則在 Visual Basic 中,這個命名空間參考為 Calc1HVA.CalcHVAs)。

  8. 選取 [方案總管] 中的方案,並選擇 [專案] 功能表中的 [屬性]。在 [方案屬性頁] 對話方塊中,將 [單一啟始專案] 設定為這個主應用程式專案。

  9. 在類別或模組檔案中,使用 AddInStore.Update 方法更新快取。使用 AddInStore.FindAddIn 方法取得語彙基元的集合,並使用 AddInToken.Activate 方法啟動增益集。

    下列程式碼示範完整的主應用程式。

    Imports System.Collections.Generic
    Imports System.Collections.ObjectModel
    Imports System.AddIn.Hosting
    Imports Calc1HVA.CalcHVAs
    
    Namespace MathHost
    
        Module MathHost1
    
            Sub Main()
                ' Assume that the current directory is the application folder, 
                ' and that it contains the pipeline folder structure.
                Dim addInRoot As String = Environment.CurrentDirectory & "\Pipeline"
    
                ' Update the cache files of the pipeline segments and add-ins.
                Dim warnings() As String = AddInStore.Update(addInRoot)
                For Each warning As String In warnings
                    Console.WriteLine(warning)
                Next
    
                ' Search for add-ins of type ICalculator (the host view of the add-in).
                Dim tokens As System.Collections.ObjectModel.Collection(Of AddInToken) = _
                    AddInStore.FindAddIns(GetType(ICalculator), addinRoot)
    
                ' Ask the user which add-in they would like to use.
                Dim calcToken As AddInToken = ChooseCalculator(tokens)
    
                ' Activate the selected AddInToken in a new application domain 
                ' with the Internet trust level.
                Dim calc As ICalculator = _
                    calcToken.Activate(Of ICalculator)(AddInSecurityLevel.Internet)
    
                ' Run the add-in.
                RunCalculator(calc)
            End Sub
    
            Private Function ChooseCalculator(ByVal tokens As Collection(Of AddInToken)) _
                    As AddInToken
    
                If (tokens.Count = 0) Then
                    Console.WriteLine("No calculators are available")
                    Return Nothing
                End If
    
                Console.WriteLine("Available Calculators: ")
                ' Show the token properties for each token in the AddInToken collection
                ' (tokens), preceded by the add-in number in [] brackets.
                Dim tokNumber As Integer = 1
                For Each tok As AddInToken In tokens
                    Console.WriteLine(vbTab & "[{0}]: {1} - {2}" & _
                            vbLf & vbTab & "{3}" & _
                            vbLf & vbTab & "{4}" & _
                            vbLf & vbTab & "{5} - {6}", _
                            tokNumber.ToString, tok.Name, _
                            tok.AddInFullName, tok.AssemblyName, _
                            tok.Description, tok.Version, tok.Publisher)
                    tokNumber = tokNumber + 1
                Next
                Console.WriteLine("Which calculator do you want to use?")
                Dim line As String = Console.ReadLine
                Dim selection As Integer
                If Int32.TryParse(line, selection) Then
                    If (selection <= tokens.Count) Then
                        Return tokens((selection - 1))
                    End If
                End If
                Console.WriteLine("Invalid selection: {0}. Please choose again.", line)
                Return ChooseCalculator(tokens)
            End Function
    
            Private Sub RunCalculator(ByVal calc As ICalculator)
                If IsNothing(calc) Then
                    'No calculators were found, read a line and exit.
                    Console.ReadLine()
                End If
                Console.WriteLine("Available operations: +, -, *, /")
                Console.WriteLine("Request a calculation , such as: 2 + 2")
                Console.WriteLine("Type 'exit' to exit")
                Dim line As String = Console.ReadLine
    
                While Not line.Equals("exit")
                    ' The Parser class parses the user's input.
                    Try
                        Dim c As Parser = New Parser(line)
                        Select Case (c.action)
                            Case "+"
                                Console.WriteLine(calc.Add(c.a, c.b))
                            Case "-"
                                Console.WriteLine(calc.Subtract(c.a, c.b))
                            Case "*"
                                Console.WriteLine(calc.Multiply(c.a, c.b))
                            Case "/"
                                Console.WriteLine(calc.Divide(c.a, c.b))
                            Case Else
                                Console.WriteLine("{0} is an invalid command. Valid commands are +,-,*,/", c.action)
                        End Select
                    Catch Ex As System.Exception
                        Console.WriteLine("Invalid command: {0}. Commands must be formated: [number] [operation] [number]", line)
                    End Try
                    line = Console.ReadLine
    
                End While
            End Sub
        End Module
    
        Class Parser
    
            Public partA As Double
            Public partB As Double
            Public action As String
    
            Friend Sub New(ByVal line As String)
                MyBase.New()
                Dim parts() As String = line.Split(" ")
                partA = Double.Parse(parts(0))
                action = parts(1)
                partB = Double.Parse(parts(2))
            End Sub
    
            Public ReadOnly Property A() As Double
                Get
                    Return partA
                End Get
            End Property
    
            Public ReadOnly Property B() As Double
                Get
                    Return partB
                End Get
            End Property
    
            Public ReadOnly Property CalcAction() As String
                Get
                    Return Action
                End Get
            End Property
        End Class
    
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.AddIn.Hosting;
    using CalcHVAs;
    
    namespace MathHost
    {
        class Program
        {
            static void Main()
            {
                // Assume that the current directory is the application folder, 
                // and that it contains the pipeline folder structure.
                String addInRoot = Environment.CurrentDirectory + "\\Pipeline";
    
                // Update the cache files of the pipeline segments and add-ins.
                string[] warnings = AddInStore.Update(addInRoot);
                foreach (string warning in warnings)
                {
                    Console.WriteLine(warning);
                }
    
                // Search for add-ins of type ICalculator (the host view of the add-in).
                Collection<AddInToken> tokens = 
                    AddInStore.FindAddIns(typeof(ICalculator), addInRoot);
    
                // Ask the user which add-in they would like to use.
                AddInToken calcToken = ChooseCalculator(tokens);
    
                // Activate the selected AddInToken in a new application domain 
                // with the Internet trust level.
                ICalculator calc = 
                    calcToken.Activate<ICalculator>(AddInSecurityLevel.Internet);
    
                // Run the add-in.
                RunCalculator(calc);
            }
    
            private static AddInToken ChooseCalculator(Collection<AddInToken> tokens)
            {
                if (tokens.Count == 0)
                {
                    Console.WriteLine("No calculators are available");
                    return null;
                }
                Console.WriteLine("Available Calculators: ");
                // Show the token properties for each token in the AddInToken collection 
                // (tokens), preceded by the add-in number in [] brackets.
                int tokNumber = 1;
                foreach (AddInToken tok in tokens)
                {
                    Console.WriteLine(String.Format("\t[{0}]: {1} - {2}\n\t{3}\n\t\t {4}\n\t\t {5} - {6}",
                        tokNumber.ToString(),
                        tok.Name,
                        tok.AddInFullName,
                        tok.AssemblyName,
                        tok.Description,
                        tok.Version,
                        tok.Publisher));
                    tokNumber++;
                }
                Console.WriteLine("Which calculator do you want to use?");
                String line = Console.ReadLine();
                int selection;
                if (Int32.TryParse(line, out selection))
                {
                    if (selection <= tokens.Count)
                    {
                        return tokens[selection - 1];
                    }
                }
                Console.WriteLine("Invalid selection: {0}. Please choose again.", line);
                return ChooseCalculator(tokens);
            }
    
            private static void RunCalculator(ICalculator calc)
            {
    
                if (calc == null)
                {
                    //No calculators were found; read a line and exit.
                    Console.ReadLine();
                }
                Console.WriteLine("Available operations: +, -, *, /");
                Console.WriteLine("Request a calculation , such as: 2 + 2");
                Console.WriteLine("Type \"exit\" to exit");
                String line = Console.ReadLine();
                while (!line.Equals("exit"))
                {
                    // The Parser class parses the user's input.
                    try
                    {
                        Parser c = new Parser(line);
                        switch (c.Action)
                        {
                            case "+":
                                Console.WriteLine(calc.Add(c.A, c.B));
                                break;
                            case "-":
                                Console.WriteLine(calc.Subtract(c.A, c.B));
                                break;
                            case "*":
                                Console.WriteLine(calc.Multiply(c.A, c.B));
                                break;
                            case "/":
                                Console.WriteLine(calc.Divide(c.A, c.B));
                                break;
                            default:
                                Console.WriteLine("{0} is an invalid command. Valid commands are +,-,*,/", c.Action);
                                break;
                        }
                    }
                    catch
                    {
                        Console.WriteLine("Invalid command: {0}. Commands must be formated: [number] [operation] [number]", line);
                    }
    
                    line = Console.ReadLine();
                }
            }
        }
    
        internal class Parser
        {
            double a;
            double b;
            string action;
    
            internal Parser(string line)
            {
                string[] parts = line.Split(' ');
                a = double.Parse(parts[0]);
                action = parts[1];
                b = double.Parse(parts[2]);
            }
    
            public double A
            {
                get { return a; }
            }
    
            public double B
            {
                get { return b; }
            }
    
            public string Action
            {
                get { return action; }
            }
        }
    }
    
    注意事項:

    此程式碼會假設管線資料夾結構位於應用程式資料夾中。如果管線資料夾結構位於其他地方,請變更設定 addInRoot 變數的程式碼行,讓變數包含管線目錄結構的路徑。

    程式碼使用 ChooseCalculator 方法列出語彙基元並提示使用者選擇增益集。RunCalculator 方法會提示使用者輸入簡單數學運算式、使用 Parser 類別剖析運算式,以及顯示增益集傳回的結果。

  10. 您可以選擇性的建置 Visual Studio 方案。

建立增益集

增益集會實作增益集檢視中所指定的方法。這個增益集會實作 Add、Subtract、Multiply 和 Divide 作業,並將結果傳回至主應用程式。

若要建立增益集

  1. 將名為 AddInCalcV1 的新專案加入至 CalculatorV1 方案。以 [類別庫] 範本為基礎。

  2. 在 [方案總管] 中,將 System.AddIn.dll 組件的參考加入至專案。

  3. 加入 Calc1AddInView 專案的專案參考。選取專案參考,然後在 [屬性] 中,將 [複製到本機] 設定為 [False]。在 Visual Basic 中,使用 [專案屬性] 的 [參考] 索引標籤,將專案參考的 [複製到本機] 設定為 [False]。

  4. 重新命名類別 AddInCalcV1。

  5. 在類別檔案中,加入 System.AddIn 的命名空間參考和增益集檢視區段:CalcAddInViews (Visual Basic 中的 Calc1AddInView.CalcAddInViews)。

  6. 套用 AddInAttribute 屬性至 AddInCalcV1 類別,以識別類別做為增益集。

  7. 讓 AddInCalcV1 類別實作代表增益集檢視的介面:CalcAddInViews.ICalculator (Visual Basic 中的 Calc1AddInView.CalcAddInViews.ICalculator)。

  8. 藉由傳回適當計算的結果,實作 ICalculator 的成員。

    下列程式碼示範完整的增益集。

    Imports System.AddIn
    Imports Calc1AddInView.CalcAddInViews
    
    Namespace CalcAddIns
    
        ' The AddInAttribute identifies this pipeline segment as an add-in.
        <AddIn("Calculator AddIn", Version:="1.0.0.0")> _
        Public Class AddInCalcV1
            Implements ICalculator
    
            Public Function Add(ByVal a As Double, ByVal b As Double) As Double _
                    Implements ICalculator.Add
                Return (a + b)
            End Function
    
            Public Function Subtract(ByVal a As Double, ByVal b As Double) As Double _
                    Implements ICalculator.Subtract
                Return (a - b)
            End Function
    
            Public Function Multiply(ByVal a As Double, ByVal b As Double) As Double _
                    Implements ICalculator.Multiply
                Return (a * b)
            End Function
    
            Public Function Divide(ByVal a As Double, ByVal b As Double) As Double _
                    Implements ICalculator.Divide
                Return (a / b)
            End Function
        End Class
    
    End Namespace
    
    using System.Collections.Generic;
    using System.AddIn;
    using CalcAddInViews;
    
    namespace CalcAddIns
    {
        // The AddInAttribute identifies this pipeline segment as an add-in.
        [AddIn("Calculator AddIn",Version="1.0.0.0")]
        public class AddInCalcV1 : ICalculator
        {
            public double Add(double a, double b)
            {
                return a + b;
            }
    
            public double Subtract(double a, double b)
            {
                return a - b;
            }
    
            public double Multiply(double a, double b)
            {
                return a * b;
            }
    
            public double Divide(double a, double b)
            {
                return a / b;
            }
        }
    }
    
  9. 您可以選擇性的建置 Visual Studio 方案。

部署管線

您現在可以建置增益集區段,並將其部署至要求的管線目錄結構。

若要將區段部署至管線

  1. 針對方案中的每個專案,使用 [專案屬性] 中的 [建置] 索引標籤 (Visual Basic 中的 [編譯] 索引標籤),設定 [輸出路徑] (Visual Basic 中的 [建置輸出路徑]) 的值。例如,如果您將應用程式資料夾命名為 MyApp,專案應該建置到下列資料夾:

    專案

    路徑

    AddInCalcV1

    MyApp\Pipeline\AddIns\CalcV1

    Calc1AddInSideAdapter

    MyApp\Pipeline\AddInSideAdapters

    Calc1AddInView

    MyApp\Pipeline\AddInViews

    Calc1Contract

    MyApp\Pipeline\Contracts

    Calc1Host

    MyApp

    Calc1HostSideAdapter

    MyApp\Pipeline\HostSideAdapters

    Calc1HVA

    MyApp

    注意事項:

    如果您是將管線資料夾結構放置在應用程式資料夾以外的位置,則必須修改表格中顯示的對應路徑。請參閱管線開發需求中有關管線目錄需求的討論。

  2. 建置 Visual Studio 方案。

  3. 請檢查應用程式和管線目錄,以確保組件有複製到正確的目錄,且沒有多餘的組件複本安裝在錯誤的資料夾中。

    注意事項:

    如果沒有將 AddInCalcV1 專案中 Calc1AddInView 專案參考的 [複製到本機] 變更為 [False],則載入器內容問題會阻礙增益集的尋找。

    如需部署至管線的詳細資訊,請參閱管線開發需求

執行主應用程式

您現在可以執行主應用程式並與增益集互動。

若要執行主應用程式

  1. 在命令提示字元,移至應用程式目錄並執行主應用程式 Calc1Host.exe。

  2. 主應用程式會尋找屬於其類型的所有可用增益集,並提示您選取增益集。輸入 1,做為唯一可用的增益集。

  3. 輸入供計算機運算的方程式,如 2 + 2。數字和運算子之間必須有空格。

  4. 輸入 exit,並按 Enter 鍵關閉應用程式。

請參閱

工作

逐步解說:在主應用程式變更時確保回溯相容性

逐步解說:在主應用程式和增益集之間傳遞集合

概念

管線開發需求

合約、檢視和配接器

管線開發

變更記錄

日期

記錄

原因

2008 年 7 月

修正文字中的錯誤。加入關於保留合約參考的備註。

客戶回函。