テキスト テンプレートを処理する独自のホストを作成できます。 基本的なカスタム ホストについては、「チュートリアル: カスタム テキスト テンプレート ホストの作成」で説明しています。 このホストを拡張して、複数の出力ファイルを生成するなどの機能を追加することができます。
このチュートリアルでは、ディレクティブ プロセッサを呼び出すテキスト テンプレートをサポートするようにカスタム ホストを拡張します。 ドメイン固有言語を定義すると、ドメイン モデルの "ディレクティブ プロセッサ" が生成されます。 ディレクティブ プロセッサを使用すると、モデルにアクセスするテンプレートをユーザーが簡単に記述できるようになり、テンプレートにアセンブリ ディレクティブとインポート ディレクティブを記述する必要性が減ります。
Note
このチュートリアルは、「チュートリアル: カスタム テキスト テンプレート ホストの作成」を基に構築されています。 まず、このチュートリアルを実行します。
このチュートリアルでは、次のタスクについて説明します。
ドメイン固有言語ツールを使って、ドメイン モデルに基づくディレクティブ プロセッサを生成します。
生成されたディレクティブ プロセッサにカスタム テキスト テンプレート ホストを接続します。
生成されたディレクティブ プロセッサを使用してカスタム ホストをテストします。
前提条件
DSL を定義するには、以下のコンポーネントをインストールしておく必要があります。
コンポーネント | Link |
---|---|
Visual Studio | http://go.microsoft.com/fwlink/?LinkId=185579 |
Visual Studio SDK | http://go.microsoft.com/fwlink/?LinkId=185580 |
Visual Studio Visualization and Modeling SDK |
Note
テキスト テンプレート変換コンポーネントは、Visual Studio 拡張機能の開発ワークロードの一部として自動的にインストールされます。 また、 [SDK、ライブラリ、およびフレームワーク] カテゴリの下にある Visual Studio インストーラーの [個別のコンポーネント] タブからインストールすることもできます。 [個別のコンポーネント] タブから Modeling SDK コンポーネントをインストールします。
さらに、「チュートリアル: カスタム テキスト テンプレート ホストの作成」では、カスタム テキスト テンプレート変換を作成する必要があります。
ドメイン固有言語ツールを使用してディレクティブ プロセッサを生成する
このチュートリアルでは、ドメイン固有言語デザイナー ウィザードを使用して、DSLMinimalTest ソリューション用のドメイン固有言語を作成します。
次の特性を持つドメイン固有言語ソリューションを作成します。
名前: DSLMinimalTest
ソリューション テンプレート: 最小言語
ファイル拡張子: min
会社名: Fabrikam
ドメイン固有言語ソリューションの作成の詳細については、「方法: ドメイン固有言語ソリューションを作成する」を参照してください。
[ビルド] メニューの [ソリューションのビルド] をクリックします。
重要
この手順では、ディレクティブ プロセッサを生成し、そのキーをレジストリに追加します。
デバッグメニューで、デバッグの開始をクリックします。
Visual Studio の 2 つ目のインスタンスが開きます。
試験的ビルドで、ソリューション エクスプローラーのファイル sample.min をダブルクリックします。
デザイナーでファイルが開きます。 モデルには、ExampleElement1 と ExampleElement2 という 2 つの要素と、それらの間のリンクがあります。
Visual Studio の第 2 インスタンスを閉じます。
ソリューションを保存し、ドメイン固有言語デザイナーを閉じます。
カスタム テキスト テンプレート ホストをディレクティブ プロセッサに接続する
ディレクティブ プロセッサを生成したら、「チュートリアル: カスタム テキスト テンプレート ホストの作成」で作成したディレクティブ プロセッサとカスタム テキスト テンプレート ホストを接続します。
CustomHost ソリューションを開きます。
[プロジェクト] メニューの [参照の追加] をクリックします。
[参照の追加] ダイアログ ボックスが開き、[.NET] タブが表示されます。
次の参照を追加します:
Microsoft.VisualStudio.Modeling.Sdk.11.0
Microsoft.VisualStudio.Modeling.Sdk.Diagrams.11.0
Microsoft.VisualStudio.TextTemplating.11.0
Microsoft.VisualStudio.TextTemplating.Interfaces.11.0
Microsoft.VisualStudio.TextTemplating.Modeling.11.0
Microsoft.VisualStudio.TextTemplating.VSHost.11.0
Program.cs または Module1.vb の先頭に、次のコード行を追加します。
StandardAssemblyReferences
プロパティのコードを見つけて、次のコードに置き換えます。Note
この手順では、ホストがサポートする、生成されたディレクティブ プロセッサに必要なアセンブリへの参照を追加します。
//the host can provide standard assembly references //the engine will use these references when compiling and //executing the generated transformation class //-------------------------------------------------------------- public IList<string> StandardAssemblyReferences { get { return new string[] { //if this host searches standard paths and the GAC //we can specify the assembly name like this: //"System" //since this host only resolves assemblies from the //fully qualified path and name of the assembly //this is a quick way to get the code to give us the //fully qualified path and name of the System assembly //--------------------------------------------------------- typeof(System.Uri).Assembly.Location, typeof(System.Uri).Assembly.Location, typeof(Microsoft.VisualStudio.Modeling.ModelElement).Assembly.Location, typeof(Microsoft.VisualStudio.Modeling.Diagrams.BinaryLinkShape).Assembly.Location, typeof(Microsoft.VisualStudio.TextTemplating.VSHost.ITextTemplating).Assembly.Location, typeof(Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation).Assembly.Location }; } }
ResolveDirectiveProcessor
関数のコードを見つけて、次のコードに置き換えます。重要
このコードには、接続先となる生成されたディレクティブ プロセッサの名前に対して、ハード コーディングされた参照が含まれています。 これを一般的にすることは簡単にできます。この場合、レジストリに列挙されているすべてのディレクティブ プロセッサを参照して、一致するものが検索されます。 そのような場合は、ホストは生成されたすべてのディレクティブ プロセッサで動作します。
//the engine calls this method based on the directives the user has //specified it in the text template //this method can be called 0, 1, or more times //--------------------------------------------------------------------- public Type ResolveDirectiveProcessor(string processorName) { //check the processor name, and if it is the name of the processor the //host wants to support, return the type of the processor //--------------------------------------------------------------------- if (string.Compare(processorName, "DSLMinimalTestDirectiveProcessor", StringComparison.InvariantCultureIgnoreCase) == 0) { try { string keyName = @"Software\Microsoft\VisualStudio\10.0Exp_Config\TextTemplating\DirectiveProcessors\DSLMinimalTestDirectiveProcessor"; using (RegistryKey specificKey = Registry.CurrentUser.OpenSubKey(keyName)) { if (specificKey != null) { List<string> names = new List<String>(specificKey.GetValueNames()); string classValue = specificKey.GetValue("Class") as string; if (!string.IsNullOrEmpty(classValue)) { string loadValue = string.Empty; System.Reflection.Assembly processorAssembly = null; if (names.Contains("Assembly")) { loadValue = specificKey.GetValue("Assembly") as string; if (!string.IsNullOrEmpty(loadValue)) { //the assembly must be installed in the GAC processorAssembly = System.Reflection.Assembly.Load(loadValue); } } else if (names.Contains("CodeBase")) { loadValue = specificKey.GetValue("CodeBase") as string; if (!string.IsNullOrEmpty(loadValue)) { //loading local assembly processorAssembly = System.Reflection.Assembly.LoadFrom(loadValue); } } if (processorAssembly == null) { throw new Exception("Directive Processor not found"); } Type processorType = processorAssembly.GetType(classValue); if (processorType == null) { throw new Exception("Directive Processor not found"); } return processorType; } } } } catch (Exception e) { //if the directive processor can not be found, throw an error throw new Exception("Directive Processor not found"); } } //if the directive processor is not one this host wants to support throw new Exception("Directive Processor not supported"); }
[ファイル] メニューの [すべてを保存] をクリックします。
[ビルド] メニューの [ソリューションのビルド] をクリックします。
ディレクティブ プロセッサを使用してカスタム ホストをテストする
カスタム テキスト テンプレート ホストをテストするには、まず、生成されたディレクティブ プロセッサを呼び出すテキスト テンプレートを作成する必要があります。 次に、カスタム ホストを実行し、テキスト テンプレートの名前を渡して、ディレクティブが正しく処理されていることを確認します。
テキスト テンプレートを作成してカスタム ホストをテストする
テキスト ファイルを作成し、
TestTemplateWithDP.tt
という名前を付けます。 ファイルの作成には、メモ帳など、任意のテキスト エディターを使用できます。次の内容をテキスト ファイルに追加します。
Note
テキスト テンプレートのプログラミング言語は、カスタム ホストのプログラミング言語と同じでなくてもかまいません。
Text Template Host Test <#@ template debug="true" inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" #> <# //this is the call to the examplemodel directive in the generated directive processor #> <#@ DSLMinimalTest processor="DSLMinimalTestDirectiveProcessor" requires="fileName='<Your Path>\Sample.min'" provides="ExampleModel=ExampleModel" #> <# //uncomment this line to test that the host allows the engine to set the extension #> <# //@ output extension=".htm" #> <# //uncomment this line if you want to see the generated transformation class #> <# //System.Diagnostics.Debugger.Break(); #> <# //this code uses the results of the examplemodel directive #> <# foreach ( ExampleElement box in this.ExampleModel.Elements ) { WriteLine("Box: {0}", box.Name); foreach (ExampleElement linkedTo in box.Targets) { WriteLine("Linked to: {0}", linkedTo.Name); } foreach (ExampleElement linkedFrom in box.Sources) { WriteLine("Linked from: {0}", linkedFrom.Name); } WriteLine(""); } #>
コードで、<YOUR PATH> を、最初の手順で作成したデザイン固有言語の Sample.min ファイルのパスに置き換えます。
ファイルを保存して閉じます。
カスタム ホストをテストする
コマンド プロンプト ウィンドウを開きます。
カスタム ホストの実行可能ファイルのパスを入力します。ただし、Enter キーはまだ押さないでください。
たとえば、次のように入力します。
<YOUR PATH>CustomHost\bin\Debug\CustomHost.exe
Note
アドレスを入力する代わりに、Windows エクスプローラーで CustomHost.exe ファイルを参照し、コマンド プロンプト ウィンドウにドラッグしてもかまいません。
空白を入力します。
テキスト テンプレート ファイルのパスを入力し、Enter キーを押します。
たとえば、次のように入力します。
<YOUR PATH>TestTemplateWithDP.txt
Note
アドレスを入力する代わりに、Windows エクスプローラーで TestTemplateWithDP.txt ファイルを参照し、コマンド プロンプト ウィンドウにドラッグしてもかまいません。
カスタム ホスト アプリケーションが実行され、テキスト テンプレート変換プロセスが開始されます。
Windows エクスプローラーで、TestTemplateWithDP.txt ファイルが格納されているフォルダーに移動します。
このフォルダーには、TestTemplateWithDP1.txt ファイルも含まれています。
このファイルを開き、テキスト テンプレート変換の結果を確認します。
生成されたテキスト出力の結果が表示され、次のようになります。
Text Template Host Test Box: ExampleElement1 Linked to: ExampleElement2 Box: ExampleElement2 Linked from: ExampleElement1