Visual Studio の項目テンプレートは自作できるのですが、どういうわけかトップレベルの名前空間を埋め込む パラメータがありません;
普通にテンプレートを作っても追加先のフォルダで名前空間の決まる $rootnamaspace$ のパラメータを利用するしかないので、~.Views と ~.Presenters の名前空間のクラスを一度に生成するなんてことができないのが不便なところ・・・
標準で用意してほしいところですが、カスタムウィザードを用意することで代用できました
EnvDTE.dll と Microsoft.VisualStudio.TemplateWizardInterface.dll、Microsoft.VisualStudio.WinRT.TemplateWizards.dll を参照したクラスライブラリプロジェクトを作成して下記のような IWizard を実装するクラスを作成します
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using EnvDTE; using Microsoft.VisualStudio.TemplateWizard; using System.IO; using System.Diagnostics; /// <summary> /// 項目テンプレート用汎用ウィザード /// </summary> public class ItemTemplateWizard : IWizard { private _DTE dte; // 概要: // テンプレートの項目を開く前にカスタム ウィザードのロジックを実行します。 // // パラメーター: // projectItem: // 開かれるプロジェクト項目。 public void BeforeOpeningFile(ProjectItem projectItem) { } // // 概要: // プロジェクトが生成を完了したときにカスタム ウィザードのロジックを実行します。 // // パラメーター: // project: // 生成を完了したプロジェクト。 public void ProjectFinishedGenerating(Project project) { } // // 概要: // プロジェクト項目が生成を完了したときにカスタム ウィザードのロジックを実行します。 // // パラメーター: // projectItem: // 生成を完了したプロジェクト項目。 public void ProjectItemFinishedGenerating(ProjectItem projectItem) { } // // 概要: // ウィザードがすべてのタスクを完了したときにカスタム ウィザードのロジックを実行します。 public void RunFinished() { } // // 概要: // テンプレート ウィザードの実行開始時にカスタム ウィザードのロジックを実行します。 // // パラメーター: // automationObject: // テンプレート ウィザードで使用されているオートメーション オブジェクト。 // // replacementsDictionary: // 置き換える標準パラメーターのリスト。 // // runKind: // ウィザードの実行の種類を示す Microsoft.VisualStudio.TemplateWizard.WizardRunKind。 // // customParams: public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams) { try { if (!(automationObject is _DTE)) { return; } this.dte = (_DTE)automationObject; var project = (Project)((object[])dte.ActiveSolutionProjects)[0]; string defaultNamespae = null; foreach (Property property in project.Properties) { if (property.Name.ToLower() == "defaultnamespace") { defaultNamespae = (string)property.Value; } } replacementsDictionary.Add("$defaultnamespace$", defaultNamespae); } catch { } } // // 概要: // 指定したプロジェクト項目をプロジェクトに追加するかどうかを示します。 // // パラメーター: // filePath: // プロジェクト項目のパス。 // // 戻り値: // プロジェクト項目をプロジェクトに追加する場合は true。それ以外の場合は false。 public bool ShouldAddProjectItem(string filePath) { return true; } }
RunStarted メソッドの中で引数の automationObject を _DTE にキャストして Project インスタンスを取得、そこから defaultnamespace のプロパティの値を参照して replacementsDictionary にパラメータとして追加します
ウィザードは GAC に登録しないと項目テンプレートで利用できないので、このクラスを含んだ状態でビルドしてできる dll を下記のようなコマンドを管理者権限で実行して登録します
cd /d %~dp0 "%ProgramFiles(x86)%\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\gacutil.exe" -i PrismMVPVM.Templates.dll
登録が終わったら項目テンプレートの .vstemplate に
<?xml version="1.0" encoding="utf-8"?> <VSTemplate Version="3.0.0" Type="Item" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.microsoft.com/developer/vstemplate/2005"> <TemplateData> <Name>MVPVM 基本ページ(Prism)</Name> <Description>MVPVM アーキテクチャの Prism フレームワーク 基本ページ</Description> <Icon>Icon.png</Icon> <TemplateGroupID>WinRT-Managed</TemplateGroupID> <ProjectType>CSharp</ProjectType> <NumberOfParentCategoriesToRollUp>1</NumberOfParentCategoriesToRollUp> <DefaultName>BasicPage.xaml</DefaultName> <ShowByDefault>false</ShowByDefault> <SortOrder>41</SortOrder> <PreviewImage>BasicPage.png</PreviewImage> <TargetPlatformName>Windows</TargetPlatformName> <RequiredPlatformVersion>6.3.0</RequiredPlatformVersion> </TemplateData> <TemplateContent> <ProjectItem ReplaceParameters="true" OpenInEditor="true" ItemType="Page" SubType="Designer" CustomTool="MSBuild:Compile" TargetFileName="$fileinputname$.xaml">BasicPage.xaml</ProjectItem> <ProjectItem ReplaceParameters="true" TargetFileName="$fileinputname$.xaml.cs">BasicPage.xaml.cs</ProjectItem> <ProjectItem ReplaceParameters="true" OpenInEditor="true" TargetFileName="/Presenters/$fileinputname$Presenter.cs">BasicPagePresenter.cs</ProjectItem> </TemplateContent> <WizardExtension> <Assembly>PrismMVPVM.Templates, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c8a122ba7c2f04d1</Assembly> <FullClassName>PrismMVPVM.Templates.ItemTemplateWizard</FullClassName> </WizardExtension> </VSTemplate>
こうするとテンプレートコードの中でトップレベルの名前空間が下記のように埋め込めるというわけですね
#region License //----------------------------------------------------------------------- // <copyright> // Copyright $registeredorganization$ $year$. // </copyright> //----------------------------------------------------------------------- #endregion namespace $defaultnamespace$.Views { using Microsoft.Practices.Prism.StoreApps; using $defaultnamespace$.Presenters; /// <summary> /// $fileinputname$ 画面 /// </summary> [PresenterView(typeof($safeitemname$Presenter))] public sealed partial class $safeitemname$ : VisualStateAwarePage, IPresenterView<$safeitemname$Presenter> { /// <summary> /// コンストラクタ /// </summary> public $safeitemname$() { this.InitializeComponent(); } #region IPresenterView<TPresenter> /// <summary> /// この画面の Presenter /// </summary> public $safeitemname$Presenter Presenter { get { return this.GetPresenter<$safeitemname$Presenter>(); } } #endregion //IPresenterView<TPresenter> } }
ちょっとめんどくさい;