チュートリアル : 拡張性のあるアプリケーションの作成
このチュートリアルでは、簡単な電卓機能を実行するアドインのパイプラインを作成する方法を説明します。 これは実用的なアプリケーションを作成するシナリオではありません。パイプラインの基本機能を示し、アドインによってホスト向けのサービスを実現する方法を示すものです。
このチュートリアルでは、次のタスクについて説明します。
Visual Studio ソリューションの作成
パイプライン ディレクトリ構造の作成
コントラクトとビューの生成
アドイン側アダプターの作成
ホスト側アダプターの作成
ホストの作成
アドインの作成
パイプラインの配置
ホスト アプリケーションの実行
このパイプラインでは、シリアル化できる型 (Double および String) のみをホストとアドイン間で受け渡します。 複合データ型のコレクションを渡す方法を示す例については、「チュートリアル : アドインとホスト間でのコレクションの受け渡し」を参照してください。
このパイプラインのコントラクトによって、4 種類の算術演算 (加算、減算、乗算、除算) に対応するオブジェクト モデルが定義されます。 ホストからアドインに計算の式 (2 + 2 など) が渡され、アドインからホストに結果が返されます。
Version 2 の計算機アドインでは計算機能がより高度になり、バージョン管理機能が備えられています。 これについては、「チュートリアル : ホスト変更時の下位互換性の確保」で解説されています。
メモ |
---|
CodePlex の「Managed Extensibility and Add-In Framework」サイトには、その他のサンプル コードや、アドイン パイプラインのビルドに使用するツールのカスタマー テクノロジ プレビューが掲載されています。 |
必須コンポーネント
このチュートリアルを完了するための要件は次のとおりです。
- Visual Studio
Visual Studio ソリューションの作成
Visual Studio のソリューションを使用して、パイプライン セグメントのプロジェクトを格納します。
パイプライン ソリューションを作成するには
Visual Studio で、Calc1Contract という名前の新規プロジェクトを作成します。 それにクラス ライブラリ テンプレートを適用します。
ソリューションに CalculatorV1 という名前を付けます。
パイプライン ディレクトリ構造の作成
アドイン モデルでは、指定したディレクトリ構造内にパイプライン セグメント アセンブリが配置される必要があります。 パイプライン構造の詳細については、「パイプライン開発の必要条件」を参照してください。
パイプライン ディレクトリ構造を作成するには
コンピューター上の任意の位置にアプリケーション フォルダーを作成します。
そのフォルダー内に、次の構造を作成します。
Pipeline AddIns CalcV1 CalcV2 AddInSideAdapters AddInViews Contracts HostSideAdapters
アプリケーション フォルダー内にパイプライン フォルダー構造を配置する必要はありません。ここでは、便宜上、そのようにしているだけです。 パイプライン フォルダー構造が別の場所にある場合は、チュートリアルの該当の手順で、コードを変更する方法について説明します。 パイプライン ディレクトリの必要条件の詳細については、「パイプライン開発の必要条件」を参照してください。
メモ このチュートリアルでは、CalcV2 フォルダーは使用しません。これは、「チュートリアル : ホスト変更時の下位互換性の確保」のプレースホルダーです。
コントラクトとビューの生成
このパイプラインのコントラクト セグメントで ICalc1Contract インターフェイスを定義します。これにより、add、subtract、multiply、および divide という 4 つのメソッドを定義します。
コントラクトを作成するには
CalculatorV1 という名前の Visual Studio ソリューションで、Calc1Contract プロジェクトを開きます。
ソリューション エクスプローラーで、次のアセンブリへの参照を Calc1Contract プロジェクトに追加します。
System.AddIn.Contract.dll
System.AddIn.dll
ソリューション エクスプローラーで、新しいクラス ライブラリ プロジェクトに追加された既定のクラスを除外します。
ソリューション エクスプローラーで、インターフェイス テンプレートを使用して、新しい項目をプロジェクトに追加します。 [新しい項目の追加] ダイアログ ボックスで、インターフェイスに ICalc1Contract という名前を付けます。
インターフェイス ファイルに、System.AddIn.Contract および System.AddIn.Pipeline への名前空間参照を追加します。
このコントラクト セグメントを完了するには、次のコードを使用します。 このインターフェイスには、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); } }
必要に応じて、Visual Studio ソリューションをビルドします。 最後の手順になるまでソリューションを実行することはできませんが、各手順のたびにソリューションをビルドすることによって、各プロジェクトが正しいことを確認できます。
アドイン ビューと、アドインのホスト ビューは、アドインの最初のバージョンの場合は特に、通常はコードが同じであるため、ビューを同時に簡単に作成できます。 この 2 つのビューの相違点は、アドイン ビューには AddInBaseAttribute 属性が必要ですが、アドインのホスト ビューには属性が必要ないということのみです。
アドイン ビューを作成するには
CalculatorV1 ソリューションに Calc1AddInView という名前の新規プロジェクトを追加します。 それにクラス ライブラリ テンプレートを適用します。
ソリューション エクスプローラーで、Calc1AddInView プロジェクトに System.AddIn.dll への参照を追加します。
ソリューション エクスプローラーで、新しいクラス ライブラリ プロジェクトに追加された既定のクラスを除外し、インターフェイス テンプレートを使用して新しい項目をプロジェクトに追加します。 [新しい項目の追加] ダイアログ ボックスで、インターフェイスに ICalculator という名前を付けます。
インターフェイス ファイルに、System.AddIn.Pipeline への名前空間参照を追加します。
このアドイン ビューを完了するには、次のコードを使用します。 このインターフェイスには、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); } }
必要に応じて、Visual Studio ソリューションをビルドします。
アドインのホスト ビューを作成するには
CalculatorV1 ソリューションに Calc1HVA という名前の新規プロジェクトを追加します。 それにクラス ライブラリ テンプレートを適用します。
ソリューション エクスプローラーで、新しいクラス ライブラリ プロジェクトに追加された既定のクラスを除外し、インターフェイス テンプレートを使用して新しい項目をプロジェクトに追加します。 [新しい項目の追加] ダイアログ ボックスで、インターフェイスに ICalculator という名前を付けます。
インターフェイス ファイルで、次のコードを使用して、アドインのホスト ビューを完了します。
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); } }
必要に応じて、Visual Studio ソリューションをビルドします。
アドイン側アダプターの作成
このアドイン側アダプターは、ビューからコントラクトへの 1 つのアダプターで構成されます。 このパイプライン セグメントにより、アドイン ビューからコントラクトに型が変換されます。
このパイプラインでは、アドインによりホストにサービスが提供され、アドインからホストに型が渡されます。 ホストからアドインには型が渡されないため、このパイプラインのアドイン側では、コントラクトからビューへのアダプターは不要です。
アドイン側アダプターを作成するには
CalculatorV1 ソリューションに Calc1AddInSideAdapter という名前の新規プロジェクトを追加します。 それにクラス ライブラリ テンプレートを適用します。
ソリューション エクスプローラーで、次のアセンブリへの参照を Calc1AddInSideAdapter プロジェクトに追加します。
System.AddIn.dll
System.AddIn.Contract.dll
隣接するパイプライン セグメントのプロジェクトへのプロジェクト参照を追加します。
Calc1AddInView
Calc1Contract
各プロジェクト参照を選択し、[プロパティ] で、[ローカルにコピーする] を [False] に設定します。 Visual Basic で、[プロジェクトのプロパティ] の [参照] タブを使用して、2 つのプロジェクト参照に対応する [ローカルにコピーする] を [False] に設定します。
プロジェクトの既定のクラス名を CalculatorViewToContractAddInSideAdapter に変更します。
クラス ファイルに、System.AddIn.Pipeline への名前空間参照を追加します。
クラス ファイルに、CalcAddInViews および CalculatorContracts という隣接セグメントに対応する名前空間参照を追加します (Visual Basic では、Visual Basic プロジェクトで既定の名前空間をオフにしていない限り、これらの名前空間参照は Calc1AddInView.CalcAddInViews および Calc1Contract.CalculatorContracts です)。
AddInAdapterAttribute 属性を CalculatorViewToContractAddInSideAdapter クラスに適用して、クラスをアドイン側アダプターとして指定します。
CalculatorViewToContractAddInSideAdapter クラスが ContractBase を継承するようにします。これによって、IContract インターフェイスの既定の実装が提供され、ICalc1Contract というパイプラインのコントラクト インターフェイスが実装されます。
ICalculator を受け取り、これをプライベート フィールドにキャッシュし、基本クラスのコンストラクターを呼び出すパブリック コンストラクターを追加します。
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); } } }
必要に応じて、Visual Studio ソリューションをビルドします。
ホスト側アダプターの作成
このホスト側アダプターは、コントラクトからビューへの 1 つのアダプターで構成されます。 このセグメントにより、コントラクタがアドインのホスト ビューに適応します。
このパイプラインでは、アドインによりホストにサービスが提供され、アドインからホストに型が渡されます。 ホストからアドインには型が渡されないため、ビューからコントラクトへのアダプターは不要です。
有効期間の管理を実装するために、ContractHandle オブジェクトを使用してコントラクトに有効期間トークンをアタッチします。 有効期間の管理を機能させるためには、このハンドルへの参照を保持する必要があります。 トークンを適用した後のプログラミングは不要です。アドイン システムでは使用されなくなったオブジェクトを破棄し、ガベージ コレクションに含められるように設定できるためです。 詳細については、「有効期間管理」を参照してください。
ホスト側アダプターを作成するには
CalculatorV1 ソリューションに Calc1HostSideAdapter という名前の新規プロジェクトを追加します。 それにクラス ライブラリ テンプレートを適用します。
ソリューション エクスプローラーで、次のアセンブリへの参照を Calc1HostSideAdapter プロジェクトに追加します。
System.AddIn.dll
System.AddIn.Contract.dll
隣接するセグメントのプロジェクトへのプロジェクト参照を追加します。
Calc1Contract
Calc1HVA
各プロジェクト参照を選択し、[プロパティ] で、[ローカルにコピーする] を [False] に設定します。 Visual Basic で、[プロジェクトのプロパティ] の [参照] タブを使用して、2 つのプロジェクト参照に対応する [ローカルにコピーする] を [False] に設定します。
プロジェクトの既定のクラス名を CalculatorContractToViewHostSideAdapter に変更します。
クラス ファイルに、System.AddIn.Pipeline への名前空間参照を追加します。
クラス ファイルに、CalcHVAs および CalculatorContracts という隣接セグメントに対応する名前空間参照を追加します (Visual Basic では、Visual Basic プロジェクトで既定の名前空間をオフにしていない限り、これらの名前空間参照は Calc1HVA.CalcHVAs および Calc1Contract.CalculatorContracts です)。
HostAdapterAttribute 属性を CalculatorContractToViewHostSideAdapter クラスに適用して、クラスをホスト側アダプター セグメントとして指定します。
CalculatorContractToViewHostSideAdapter クラスが、Calc1HVAs.ICalculator (Visual Basic では Calc1HVA.CalcHVAs.ICalculator) というアドインのホスト ビューを表すインターフェイスを実装するようにします。
ICalc1Contract というパイプライン コントラクト タイプを受け取るパブリック コンストラクターを追加します。 このコンストラクターは、コントラクトへの参照をキャッシュする必要があります。 コントラクタの新しい ContractHandle を作成およびキャッシュして、アドインの有効期間を管理する必要もあります。
重要 有効期間の管理には、ContractHandle が重要です。ContractHandle オブジェクトへの参照を保持していないと、ガベージ コレクションによってオブジェクトが再利用され、プログラムで予期していないタイミングでパイプラインがシャットダウンすることになります。これは、AppDomainUnloadedException のような診断が困難なエラーの原因となる可能性があります。シャットダウンはパイプラインの正常な段階の 1 つであるため、有効期間を管理するコードでこの状態をエラーとして検出する方法はありません。
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); } } }
必要に応じて、Visual Studio ソリューションをビルドします。
ホストの作成
ホスト アプリケーションは、アドインのホスト ビューを利用してアドインと対話します。 AddInStore クラスと AddInToken クラスを利用したアドイン探索とアクティベーション メソッドを使って、次の処理を実行します。
パイプライン情報とアドイン情報のキャッシュを更新する。
指定されたパイプライン ルート ディレクトリで、ICalculator というホスト ビュー タイプのアドインを検索する。
使用するアドインを指定するように促すメッセージを表示する。
セキュリティ信頼レベルが指定された新しいアプリケーション ドメインで、選択されたアドインをアクティブにする。
RunCalculator カスタム メソッドを実行する。これにより、アドインのホスト ビューの指定に従ってアドインのメソッドが呼び出されます。
ホストを作成するには
CalculatorV1 ソリューションに Calc1Host という名前の新規プロジェクトを追加します。 これにコンソール アプリケーション テンプレートを適用します。
ソリューション エクスプローラーで、Calc1Host プロジェクトに System.AddIn.dll アセンブリへの参照を追加します。
Calc1HVA プロジェクトへのプロジェクト参照を追加します。 プロジェクト参照を選択し、[プロパティ] で、[ローカルにコピーする] を [False] に設定します。 Visual Basic で、[プロジェクトのプロパティ] の [参照] タブを使用して、[ローカルにコピーする] を [False] に設定します。
クラス ファイル (Visual Basic ではモジュール) の名前を MathHost1 に変更します。
Visual Basic で、[プロジェクトのプロパティ] ダイアログ ボックスの [アプリケーション] タブを使用して、[スタートアップ オブジェクト] を [Sub Main] に設定します。
クラス ファイルまたはモジュール ファイルに、System.AddIn.Hosting への名前空間参照を追加します。
クラス ファイルまたはモジュール ファイルに、CalcHVAs というアドインのホスト ビューに対応する名前空間参照を追加します (Visual Basic では、Visual Basic プロジェクトで既定の名前空間をオフにしていない限り、この名前空間参照は Calc1HVA.CalcHVAs です)。
ソリューション エクスプローラーでソリューションを選択し、[プロジェクト] メニューの [プロパティ] をクリックします。 ソリューションの [プロパティ ページ] ダイアログ ボックスで、[シングル スタートアップ プロジェクト] をこのホスト アプリケーション プロジェクトに設定します。
クラス ファイルまたはモジュール ファイルで、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 クラスを使用して式を解析し、アドインから返される結果を表示します。
必要に応じて、Visual Studio ソリューションをビルドします。
アドインの作成
アドインにより、アドイン ビューで指定されたメソッドを実装します。 このアドインにより、Add、Subtract、Multiply、および Divide の各処理が実装され、ホストに結果が返されます。
アドインを作成するには
CalculatorV1 ソリューションに AddInCalcV1 という名前の新規プロジェクトを追加します。 それにクラス ライブラリ テンプレートを適用します。
ソリューション エクスプローラーで、プロジェクトに System.AddIn.dll アセンブリへの参照を追加します。
Calc1AddInView プロジェクトへのプロジェクト参照を追加します。 プロジェクト参照を選択し、[プロパティ] で、[ローカルにコピーする] を [False] に設定します。 Visual Basic で、[プロジェクトのプロパティ] の [参照] タブを使用して、プロジェクト参照に対応する [ローカルにコピーする] を [False] に設定します。
クラス名を AddInCalcV1 に変更します。
クラス ファイルに、CalcAddInViews (Visual Basic では Calc1AddInView.CalcAddInViews) という、System.AddIn およびアドイン ビュー セグメントへの名前空間参照を追加します。
AddInAttribute 属性を AddInCalcV1 クラスに適用して、クラスをアドインとして指定します。
AddInCalcV1 クラスが、CalcAddInViews.ICalculator (Visual Basic では Calc1AddInView.CalcAddInViews.ICalculator) というアドイン ビューを表すインターフェイスを実装するようにします。
適切な計算結果を返すことによって、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; } } }
必要に応じて、Visual Studio ソリューションをビルドします。
パイプラインの配置
これで、アドイン セグメントを作成し、必要なパイプライン ディレクトリ構造内に配置する準備ができました。
セグメントをパイプラインに配置するには
ソリューション内の各プロジェクトについて、[プロジェクトのプロパティ] の [ビルド] タブ (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
メモ アプリケーション フォルダー以外の場所にパイプライン フォルダー構造を配置した場合は、それに応じて、表内のパスを変更する必要があります。パイプライン ディレクトリの必要条件の詳細については、「パイプライン開発の必要条件」を参照してください。
Visual Studio ソリューションをビルドします。
アプリケーション ディレクトリおよびパイプライン ディレクトリをチェックして、アセンブリが正しいディレクトリにコピーされ、余分なアセンブリが間違ったフォルダーにインストールされていないことを確認します。
メモ AddInCalcV1 プロジェクト内で、Calc1AddInView プロジェクト参照について、[ローカルにコピーする] を [False] に変更しなかった場合、ローダー コンテキストの問題が原因で、アドインを見つけることができません。
パイプラインへの配置の詳細については、「パイプライン開発の必要条件」を参照してください。
ホスト アプリケーションの実行
これで、ホストを実行し、アドインと対話する準備が整いました。
ホスト アプリケーションを実行するには
コマンド プロンプトで、アプリケーション ディレクトリに移動し、ホスト アプリケーション Calc1Host.exe を実行します。
対応する型のアドインがすべて検索され、アドインの選択を求めるメッセージが表示されます。 使用できるアドインは 1 つのみであるため、「1」を入力します。
電卓に数式を入力します。たとえば、「2 + 2」などと入力します。 数字と演算子の間には空白が必要です。
「exit」と入力し、Enter キーを押して、アプリケーションを閉じます。
参照
処理手順
チュートリアル : アドインとホスト間でのコレクションの受け渡し