F# プログラミング

F#/C# の VSIX プロジェクト テンプレートを作成する

Dan Mohl

コード サンプルのダウンロード

ソフトウェア開発者には、複雑なソリューションを、不具合なく、短時間で提供することがますます求められています。生産性の低下は、多くの場合、F#、C#、または Visual Basic のプロジェクトを新しく作成する場合に必要な初期セットアップの工程で起こります。このように毎回行うプロジェクトのセットアップ作業を減らす最善の方法は、Visual Studio 拡張機能 (VSIX) プロジェクト テンプレートを作成することです。

ソフトウェアの開発標準を普及させたい場合、新製品を紹介したい場合、新しいテクノロジへのクイック起動を提供したい場合なども VSIX プロジェクト テンプレートを作成します。どのような動機があるにせよ、VSIX プロジェクト テンプレートを作成する能力を開発手段の 1 つとして身に着けておけば必ずメリットがあります。

今回の記事では、C# ASP.NET MVC 3 Web アプリケーション、サーバー側コードを含む F# ライブラリ、および単体テストの保持に使用できる F# ライブラリから構成される VSIX プロジェクト テンプレートの作成方法を紹介します。また、プロジェクト テンプレートに柔軟性と機能を追加するために使用できる高度な技法もいくつか習得します。この記事を最後までお読みいただけば、独自のカスタム プロジェクト テンプレートを作成して、前述のような時間の無駄となる作業を大幅に削減するための知識が身に付いているでしょう。

セットアップする

始める前に、開発環境をセットアップするため、いくつかの作業を必ず完了させておきます。まず、F# コンポーネントと C# コンポーネントが付属する、Visual Studio 2010 Professional 以上のバージョンがインストールされていることを確認します。次に、Visual Studio 2010 SDK を bit.ly/vs-2010-SDK (英語) からダウンロードしてインストールします。Visual Studio 2010 SDK には、VSIX プロジェクトを作成するために必要なものがすべて揃っています。マルチプロジェクト テンプレートを作成する際の面倒な作業を減らすには、Export Template Wizard も bit.ly/export-template-wiz からダウンロードしてインストールします。最後に、ここで紹介する例を実行するため、ASP.NET MVC 3 Tools Update を bit.ly/mvc3-tools-update からダウンロードしてインストールします。この更新プログラムでは、NuGet 1.2 をはじめとして、便利な機能とツールが多数用意されています。詳細については、bit.ly/introducing-mvc3-tools-update (英語) を参照してください。

最初のアプリケーションをビルドする

これで環境をセットアップできたので、基本アプリケーションをビルドする準備が整いました。基本アプリケーションとは、Visual Studio の新規プロジェクト ウィザードからプロジェクト テンプレートを起動するたびに作成されるアプリケーションです。これにより、毎回行うプロジェクトの初期作業による時間の浪費を削減するために必要なものをセットアップできます。この時点で開発するソリューションは、必要に応じて単純にも複雑にもすることが可能です。

まず、MsdnWeb という名前を付けた C# ASP.NET MVC 3 Web アプリケーションのプロジェクトを作成する必要があります。このプロジェクトの役割は、ソリューション全体のプレゼンテーション層を提供することです。Visual Studio で新規プロジェクト ウィザードを起動し、[Visual C#]、[Web] を順にクリックして、[ASP.NET MVC 3 Web アプリケーション] を選択します。この例では、"空の" テンプレートと Razor ビュー エンジンを確認し、さらに [HTML5 セマンティック マークアップを使用する] チェック ボックスがオンになっていることを確認し、[OK] をクリックします。Visual Studio がプロジェクトを生成し終わったら、Global.asax ファイルと Global.asax.cs ファイルに移動します。Global.asax のコードの大部分は F# で記述するため、Global.asax.cs ファイルを削除して、Global.asax マークアップを図 1 のように更新します。このプロジェクトの最終手順として、Views フォルダーに Home というフォルダーを新規作成し、作成したフォルダーに Index という新しいビューを追加します。

Updating the Global.asax Markup
図 1 Global.asax マークアップの更新

次に、MsdnWebApp という F# ライブラリ プロジェクトを新規作成し、Visual Studio が既定で作成する .fs ファイルと .fsx ファイルを削除します。このプロジェクトの主な目的は、ビューを操作するコントローラー、モデル、およびその他のサーバー側のコードを収容することです。このプロジェクトは F# プロジェクトのため、F# によって提供される無駄のない、明確で簡潔なスタイルを用いてサーバー側コードを作成することができます。このプロジェクトを前述の目的に使用するには、System.Web アセンブリ、System.ComponentModel.DataAnnotations アセンブリ、System.Web.Abstractions アセンブリ、および System.Web.Mvc アセンブリ (バージョン 3.0 以降) への参照を追加する必要があります。また、図 2 に示すコードを収容する Global.fs ファイルを追加することも必要です。

図 2 Global.fs ファイル

namespace MsdnWeb
 
open System
open System.Web
open System.Web.Mvc
open System.Web.Routing
 
type Route = { controller : string
               action : string
               id : UrlParameter }
 
type Global() =
  inherit System.Web.HttpApplication()
 
  static member RegisterRoutes(routes:RouteCollection) =
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
    routes.MapRoute("Default",
                    "{controller}/{action}/{id}",
                    { controller = "Home"; action = "Index"
                      id = UrlParameter.Optional } )
 
  member this.Start() =
    AreaRegistration.RegisterAllAreas()
    Global.RegisterRoutes(RoutTable.Routes)

さらに、次のコードを収容する HomeController.fs ファイルの追加も必要です。

namespace MsdnWeb.Controllers
 
Open System.Web
Open System.Web.Mvc
 
[<HandleError>]
type HomeController() =
  inherit Conroller()
  member this.Index() =
    this.View() :> ActionResult

最初のアプリケーションのビルドにおける最後の作業として、もう 1 つの F# ライブラリ プロジェクトを作成して MsdnWebAppTests という名前を付けます。その名のとおり、MsdnWebAppTests プロジェクトは、MsdnWebApp プロジェクトの単体テストを保持することを目的としています。MsdnWebApp プロジェクトを運用可能なバージョンにするには、前もって単体テストを実施することになります。ただし、作業の簡潔さを保つために、Visual Studio が既定で生成する .fs ファイルと .fsx ファイルを削除して空にしたプロジェクトを、今後テストを作成する際のコンテナーとして残しておきます。このプロジェクトに追加できるコードの例を確認するには、bit.ly/fsunit-mvc3-tests (英語) で FsUnit.MvcSample NuGet パッケージをインストールしてください。

VSIX プロジェクト テンプレートを作成する

ここで説明するプロジェクト テンプレートの例には、複数の目標あります。ここからは、この目標に基づいて説明します。

  1. C# プロジェクトと 2 つの F# プロジェクトから構成される VSIX プロジェクト テンプレートを提供する
  2. プロジェクトの新規作成中に、各プロジェクトを共有ソリューションに動的に追加する
  3. プロジェクト テンプレートが呼び出されるたびに、プログラムによってすべての必要なプロジェクト参照を追加する
  4. さまざまな NuGet パッケージを、作成した ASP.NET MVC 3 Web アプリケーションにインストールする
  5. プロジェクトの作成に関して、ユーザーがさまざまなオプションを指定できる UI を提供する

Visual Studio には、1 つ目の目標をいとも簡単に達成できる、充実した機能拡張モデルが用意されています。このモデルを最も簡単に利用するには、[ファイル] メニューの [Export Template as VSIX] をクリックして Export Template Wizard を起動します。これにより、Visual Studio から VSIX パッケージを作成するウィザードが表示され、選択した複数のプロジェクトを 1 つの VSIX パッケージに圧縮できます。この方法は、シンプルなマルチプロジェクトのシナリオには対処可能ですが、2 ~ 5 つ目の目標のようにさらに高度な要求には対処できません。これらに対処するには、もう少し機能が必要です。

足りない機能は、IWizard インターフェイスを介した構成という形で提供されます。このインターフェイスは、通常、テンプレート ウィザードを作成する際に参照されます。簡単なテンプレート ウィザードを F# でビルドするには、新しい F# ライブラリ プロジェクトを作成し、IWizard インターフェイスを実装したクラス (図 3 参照) を追加して、EnvDTE および Microsoft.VisualStudio.TemplateWizardInterface への参照を追加する必要があります。

図 3 IWizard インターフェイスの実装

namespace MsdnFsTemplateWizard
 
open System
open System.Collections.Generic
open EnvDTE
open Microsoft.VisualStudio.TemplateWizard
 
type TemplateWizard() =
  interface IWizard with
    member this.RunStarted (automationObject:Object,)
           replacementsDictionary:Dictionary<string,string>,
           runKind:WizardRunKind, customParams:Object[]) =
           "Not Implemented" |> ignore
    member this.ProjectFinishedGenerating project = "Not Implemented" |> ignore
    member this.ProjectItemFinishedGenerating projectItem =
      "Not Implemented" |> ignore
    member this.ShouldAddProjectItem filePath = true
    member this.BeforeOpeningFile projectItem = "Not Implemented" |> ignore
    member this.RunFinished() = "Not Implemented" |> ignore

プログラムによるプロジェクト参照の追加や NuGet パッケージのインストールなど、より高度な機能に対処するには、EnvDTE80、VSLangProj、VSLangProj80、Microsoft.VisualStudio.ComponentModelHost、Microsoft.VisualStudio.OLE.Interop、Microsoft.VisualStudio.Shell、Microsoft.VisualStudio.Shell.Interop、Microsoft.VisualStudio.Shell.Interop.8.0、NuGet.Core (バージョン 1.2 以降) および NuGet.VisualStudio (バージョン 1.2 以降) への参照も追加する必要があります。先ほどの手順に従って環境をセットアップしている場合は、これらすべてのライブラリをローカル コンピューターで利用できます。主要ライブラリのうちのいくつかは、この記事に付属するソース コードの lib フォルダーでも確認できます。ソース コードについては、fsharpmvc3vsix.codeplex.com (英語) を参照してください。

基本テンプレート ウィザードをビルドする最後の手順として、テンプレート ウィザード アセンブリに署名する必要があります。キー ファイルがなければ、まず厳密名を付けたキー (.snk) ファイルを生成することが必要です (生成方法の詳細については、https://msdn.microsoft.com/ja-jp/library/6f05ezxy.aspx を参照してください)。.snk ファイルを生成したら、プロジェクトのプロパティで [ビルド] タブを開き、[その他のフラグ] ボックスに次のように入力すると (<Path> および <snk File Name> の値は、独自の .snk ファイルの値に置き換えてください)、F# テンプレート ウィザード アセンブリに署名できます。

'--keyfile:"<Path><snk File Name>.snk"'

このテンプレート ウィザードを使用するには、署名したテンプレート ウィザード アセンブリを参照するマルチプロジェクト テンプレートを作成する必要があります。これを最も簡単に行うには、Visual Studio 2010 拡張機能の Export Template Wizard を使用してプロセスを開始し、その後手動で結果を調整します。[ファイル] メニューの [Export Template as VSIX] をクリックし、表示されたウィザードで MsdnWeb プロジェクト、MsdnWebApp プロジェクト、および MsdnWebAppTests プロジェクトを選択して [Next] をクリックします。その後のページで、Visual Studio の新規プロジェクト ウィザード のウィンドウに表示させるテンプレート名と説明を入力し、ウィザード アセンブリにおけるテンプレート ウィザードの DLL ファイルの場所を指定します。[Next] をクリックし、[Automatically import the template into Visual Studio] チェック ボックスをオフにして [Finish] をクリックします。その後 Visual Studio によって、VSIX パッケージの作成、エクスプローラーの起動、および VSIX ファイルを格納しているディレクトリへの移動が行われます。

この操作は出発点としては優れていますが、その後は自身の手で実際に操作し、手動でいくつか変更を加える必要があります。VSIX ファイルは単に拡張子が異なる .zip ファイルなので、ファイル拡張子を .zip に変えてすべてのファイルを抽出すれば、このパッケージの中身を確認できます。完了したら、抽出過程で明らかになるフォルダー内のソリューション ディレクトリへ移動して、内部の圧縮ファイルを抽出します。この抽出過程で、プロジェクト テンプレートと .vstemplate ファイルを構成するプロジェクトが表示されます。

このプロジェクト テンプレートの目標を満たすには、この .vstemplate ファイルを変更する必要があります。まず、ファイル名を MsdnFsMvc3.vstemplate に変更します。この .vstemplate ファイルはシンプルな XML ファイルなので、任意のテキスト エディターでファイルを開けば、次のことが可能になります。

  1. Visual Studio の新規プロジェクト ウィザードに表示する、このプロジェクト テンプレートについての情報が、<Name> 要素と <Description> 要素に含まれていることを確認する。
  2. <ProjectType> 要素の値を "FSharp" に変更する。
  3. <ProjectCollection> 要素のすべての子要素を削除する。

次に、このファイルを保存して閉じた後、3 つのフォルダーと変更済みの .vstemplate ファイルを、MsdnFsMvc3.zip という 1 つのファイルに圧縮します。

この時点では、MsdnFsMvc3.zip ファイルを簡単に VSIX パッケージに組み込み直すことができますが、その場合はデバッグ サポートによるパッケージのテスト機能や拡張機能がないままになります。この種の作業に Visual Studio を使用できると、状況が大きく改善されます。さいわい、事前インストールした Visual Studio 2010 SDK には、この実現に必要なツールが用意されています。まず、[Visual C#]、[Extensibility] を順にクリックし、表示された新規プロジェクト ウィザードで新しい VSIX プロジェクトを作成する必要があります。Visual Studio によって作成されるプロジェクトには、単純なダブルクリックで確認および編集が可能な source.extension.vsixmanifest ファイルが含まれています。次に、作成したプロジェクト テンプレートについての基本メタデータ情報を入力します。図 4 に例を示します。

Filling out the Metadata
図 4 メタデータの入力

これで、Visual Studio で MsdnFsMvc3.zip ファイルを VSIX プロジェクトに追加できるようになります。追加するには、まずエクスプローラーで VSIX プロジェクトのルート フォルダーに移動して、ProjectTemplates というフォルダーを新規作成します。このフォルダーには、ASPNET というフォルダーを新しく追加します。この 2 つ目のフォルダーを作成することで、プロジェクト テンプレートのプロジェクト サブタイプが決まります。次に、MsdnFsMvc3.zip ファイルを ASPNET フォルダーにコピーします。

Visual Studio に戻り、source.extension.vsixmanifest ファイルのデザイン ビューで [コンテンツの追加] ボタンをクリックします。図 5 は、[コンテンツの追加] ダイアログ ボックスで指定できるエントリを示しています。

Adding Content in the Design View of a Manifest File
図 5 マニフェスト ファイルのデザイン ビューにおけるコンテンツの追加

このプロセスによって VSIX プロジェクトで自動作成されるディレクトリ構造は、少々調整が必要になります。調整するには、[ProjectTemplates] フォルダーを右クリックして、ASPNET というフォルダーを新しく作成します。最後に、圧縮したファイルを [ProjectTemplates] フォルダーから [ASPNET] フォルダーに移動し、既存のファイルを上書きするかどうか確認するメッセージが表示されたら [Yes] (はい) をクリックします。すぐにソリューションをビルドすると、Visual Studio が作成する VSIX プロジェクト テンプレートに問題がないことがわかります。必要であれば、Visual Studio が作成した .vsix ファイルをダブルクリックして、表示されるインストール ウィザードの指示に従うことで、このプロジェクト テンプレートを Visual Studio に追加することができます。

プロジェクト テンプレートを拡張する

ここまでの手順を完了すると、このテンプレートの 1 つ目の目標が実現され、残りの目標実現に向けての土台が築かれます。残りの目標は、主にテンプレート ウィザードの IWizard 実装の RunFinished メソッドに、コードを追加することで実現できます。このテンプレートについて残りの目標を達成するために必要なコードを確認しましょう。

図 6 では、プロジェクトの作成中に、各プロジェクトをソリューションに動的に追加するという 2 つ目の目標を達成するのに必要なコードを示しています。

図 6 ソリューションへのプロジェクトの動的追加

// This method can be found in the full source
// as part of the TemplateWizard class.
member this.RunFinished() =
 
  // Non-relevant code omitted.
   
  // this.solution is set in the RunStarted method.
  let templatePath = this.solution.GetProjectTemplate("MsdnFsMvc3.zip", "FSharp")
  let AddProject status projectVsTemplateName projectName =
    // this.dte2 is set in the RunStarted method
    this.dte2.StatusBar.Text <- status
    let path =
      templatePath.Replace("MsdnFsMvc3.vstemplate", projectVsTemplateName)
    this.solution.AddFromTemplate(path,
      Path.Combine(this.destinationPath, projectName),
      projectName, false) |> ignore
 
  // webName and webAppName are values that have been
  // bound to strings that identify specific projects.     
  AddProject "Installing the C# Web project..."
    (Path.Combine("MsdnWeb", "MsdnWeb.vstemplate")) webName
  AddProject "Adding the F# Web App project..."
    (Path.Combine("MsdnWebApp", "MsdnWebApp.vstemplate")) webAppName
 
  // Non-relevant code omitted.

図 6 に示したメソッドの 1 行目のコードは、新規プロジェクト ウィザードが起動されたコンピューターでのマルチプロジェクト テンプレートの場所を返します。2 行目は、AddProject という関数を定義します。この関数には、Visual Studio のステータス バーを更新するのに必要なコードが用意されています。また、この関数で目的のプロジェクト テンプレートに対応する適切な .vstemplate ファイルの指定や、テンプレートからソリューションへのプロジェクトの追加を行います。コードの最終行では、MsdnWeb プロジェクトおよび MsdnWebApp プロジェクトに対して AddProject 関数を呼び出します。必要であれば、MsdnWebAppTests プロジェクトに対しても AddProject 関数と同様の呼び出しを追加することが可能です。

必要なあらゆるプロジェクト参照を動的に追加するという 3 つ目の目標を達成するには、まず、プロジェクト名とソリューションを構成する関連 Project オブジェクトのマップを作成する必要があります (F# のマップの詳細については、https://msdn.microsoft.com/ja-jp/library/ee353686.aspx を参照してください)。ソリューションの Projects のコレクションを引数に指定して、BuildProjectMap というカスタム関数を呼び出すと、マップを作成することができます。

このマップは、次に示すように "projects" という値にバインドします。

// This function can be found in the full source
// as part of the ProjectService module.
let BuildProjectMap (projects:Projects) =
  projects
  |> Seq.cast<Project>
  |> Seq.map(fun project -> project.Name, project)
  |> Map.ofSeq
 
// This method can be found in the full source
// as part of the TemplateWizard class.
member this.RunFinished() =
 
  // Non-relevant code omitted.
 
  // this.dte is set in the RunStarted method.
  let projects = BuildProjectMap (this.dte.Solution.Projects)
 
  // Non-relevant code omitted.

プロジェクトのマップを作成したので、別のカスタム関数を呼び出して、プロジェクト参照を追加するプロセスに着手できます。次のコードの 1 行目は、組のリストを作成します。

// This method can be found in the full source
// as part of the TemplateWizard class.
member this.RunFinished() =
 
  // Non-relevant code omitted.   
 
  // webName, webAppName and webAppTestsName are values that have been
  // bound to strings that are used to identify specific projects.     
  [(webName, webAppName); (webAppTestsName, webAppName)]
  |> BuildProjectReferences projects
 
  // Non-relevant code omitted.

リストの各組は、対象とするプロジェクト名の後に、参照中のプロジェクト名を示すことで表現しています。たとえば、最初の組は、対象プロジェクト名が "MsdnWeb" で、関連するプロジェクト参照の名前が "MsdnWebApp" であることを表しています。作成後、このリストを BuildProjectReferences 関数にパイプします。

次のコードは、BuildProjectReferences 関数を示します。

// This function can be found in the full source
// as part of the ProjectService module.
let BuildProjectReferences (projects:Map<string, Project>) projectRefs =
  projectRefs
  |> Seq.iter (fun (target,source) ->
              AddProjectReference (projects.TryFind target)
                (projects.TryFind source))

この関数は、組のリストを受け取って反復処理を行い、名前を基にプロジェクトのマップから適切な Project オブジェクトを取得して、実際の処理を行うために AddProjectReference 関数を呼び出します。

AddProjectReference 関数は、次に示すように、target 引数と projToReference 引数の両方に適切なプロジェクトが含まれていることを確認して、プロセスを完了します。

// This function can be found in the full source
// as part of the ProjectService module.
let AddProjectReference (target:Option<Project>)
  (projToReference:Option<Project>) =
  if ((Option.isSome target) && (Option.isSome projToReference)) then
      let vsTarget = target.Value.Object :?> VSProject
      vsTarget.References
      |> Seq.cast<Reference>
      |> Seq.filter(fun (reference) -> reference.Name = projToReference.Value.Name)
      |> Seq.iter(fun reference -> reference.Remove())
      vsTarget.References
        .AddProject((projToReference.Value.Object :?> VSProject).Project)
        |> ignore

適切なプロジェクトが含まれていると、AddProjectReference 関数によってあらゆる既存の参照が削除されます。最後に、この関数によりプロジェクトへの参照が追加されます。

このプロジェクト テンプレートの 4 つ目の目標は、ASP.NET MVC チームが最近導入した概念です。この概念により、近い将来拡張されると思われるライブラリまたはフレームワークに参照を追加する優れた方法が提供されます。ASP.NET MVC 3 Tools Update に付属する NuGet 1.2 には、NuGet.VisualStudio というアセンブリが用意されていて、テンプレート ウィザード内から簡単に NuGet パッケージをインストールできます。ASP.NET MVC 3 Tools Update をインストールすると、いくつかの NuGet パッケージもローカル コンピューターに追加され、プロジェクト作成中のこれらのパッケージのインストールがより高速になります。

NuGet パッケージをインストールするために使用するサンプルには、いくつかの異なる関数があります。最も重要なものを次に示します。

// This function can be found in the full source
// as part of the NuGetService module.
let InstallPackages (serviceProvider:IServiceProvider) (project:Project) packages =
  let componentModel =
    serviceProvider.GetService(typeof<SComponentModel>) :?> IComponentModel
  let installer = componentModel.GetService<IVsPackageInstaller>()
  let nugetPackageLocalPath = GetNuGetPackageLocalPath()
  packages
  |> Seq.iter (fun packageId ->
              installer.InstallPackage(nugetPackageLocalPath,
                project, packageId, null, false))

この関数の先頭 3 行のコードは、指定されたプロジェクトでさまざまな NuGet パッケージをインストールする、IVsPackageInstaller インターフェイスの具体的な実装を取得するのに使用します。コードの 4 行目は、システム レジストリにアクセスして ASP.NET MVC 3 のインストール パスを決定する、GetNuGetPackageLocalPath 関数を呼び出します。渡されたパッケージ名のリストは、反復処理して各パッケージをインストールする、Seq.iter 関数にパイプします。

テンプレート ウィザードにこれらの機能をすべて実装したので、コンテンツの種類を [Template Wizard] (テンプレート ウィザード) に指定して、テンプレート ウィザード プロジェクトをコンテンツとして VSIX プロジェクトに追加する必要があります。図 7 は、入力後の [コンテンツの追加] ダイアログ ボックスを示しています。これで、2 ~ 4 つ目の目標を実現しました。

The Completed Add Content Window
図 7 [コンテンツの追加] ダイアログ ボックス

Windows Presentation Foundation UI を追加する

最後の目標、つまり、プロジェクトの作成プロセス中にユーザーの情報を集めるのに使用する UI を追加するという目標を達成するためのプロセスは、ここ数年間さほど変化していません。2007 年の O’Reilly Media Inc. の記事 (oreil.ly/build-vs-proj-wiz、英語) では、このプロセスについて優れた概要が提供されています。プロセスの前提は変わっていませんが、この Windows Presentation Foundation (WPF) の機能を実装し、作成済みのプロジェクト テンプレートに関連付けるには、把握しておくべき事項がいくつかあります。

まず、C# の新しいユーザー コントロール ライブラリを作成する必要があります。対象とするフレームワークを .NET Framework 4 Client Profile から .NET Framework 4 に変更します。次に、既定の UserControl1.xaml を削除して新しい WPF ウィンドウを追加します。これにより、好みのメソッドで XAML を操作して目的の UI を設計できるようになります。最後に、必要なプロパティをすべて公開して、必要なイベント ハンドラーをすべて定義する必要があります。WPF ウィンドウ用の分離コードの簡単な例を以下に示します。

// This can be found in the full source as part of the MsdnCsMvc3Dialog class.
 
public bool IncludeTestsProject { get; set; }
 
private void btnOk_Click(object sender, RoutedEventArgs e)
{
  IncludeTestsProject =
    cbIncludeTestsProject.IsChecked.HasValue ?
      cbIncludeTestsProject.IsChecked.Value : false;
  DialogResult = true;
  Close();
}
 
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
  Close();
}

望みどおりの UI を手に入れたら、アセンブリに署名する必要があります。次に、プロジェクトを (コンテンツの種類がテンプレート ウィザードのコンテンツとして) VSIX プロジェクトに追加します。その後、作成した UI を含むプロジェクトへの参照をテンプレート ウィザード プロジェクトに追加します。これらがすべて完了したら、以下に示すように、UI を表示して結果を取得するコードを IWizard 実装の RunStarted メソッドに加えます。

// This method can be found in the full source
//as part of the TemplateWizard class.
member this.RunStarted () =
 
  // Non-relevant code omitted.
 
  let dialog = new TemplateView()
  match dialog.ShowDialog().Value with
  | true ->
    this.includeTestProject <- dialog.IncludeTestsProject
  | _ ->
    raise (new WizardCancelledException())

最後に、テンプレート ウィザードの RunFinished メソッドに次のコードを追加します。

 

// This method can be found in the full source
//as part of the TemplateWizard class.
member this.RunFinished() =
 
  // Non-relevant code omitted
 
  // webAppTestsName is a value that has been bound
  // to a string that represents the tests project.     
  if this.includeTestProject then
    AddProject "Adding the F# Web App Tests project..."
      (Path.Combine("MsdnWebAppTests",
        "MsdnWebAppTests.vstemplate")) webAppTestsName
  // Non-relevant code omitted.

再利用と時間短縮

F#/C# の VSIX プロジェクト テンプレートの作成は、毎回行うプロジェクトのセットアップ作業を再利用し、浪費していた時間を短縮できる簡単な方法です。習得したこれらの技術があれば、シナリオに合わせて複雑さを加減するプロジェクト テンプレートを作成して、生産性の向上を実現できます。

Daniel Mohl は、マイクロソフトの MVP であり、F# の事情通です。彼のブログは blog.danielmohl.com (英語) で、Twitter は twitter.com/dmohl (英語) でフォローすることができます。

この記事のレビューに協力してくれた技術スタッフの Elijah ManorChris MarinosRichard Minerich に心より感謝いたします。