Visual Studio 2010のUMLモデルからいろんなモノを生成する – その1


さて、単にモデルにアクセスするだけでは、実につまらないので、早速アクセスして取得した情報を活用して、いろんなモノを生成する方法を説明します。


まずはテキストファイルです。
多分すぐ思いつくのは、前回説明したやり方でUMLモデルにアクセスし、TextWriterのWriteLineを使ってテキストを作成し、ファイルに流し込む方法でしょう。しかしこれだと、生成するテキスト一行毎に、


writer.WriteLine("お名前は?{0}...",model.Name,...);


な感じになり、凄く見通しも悪く、直観的でないですね。
こんな時には、ずっと前からVisual Studioの機能として提供されている、T4 Templateを使います。が、なんと、Visual Studio 2010ではText Templatingの機能が大幅に強化されていますっ!!(パチパチパチパチ)。


MDD好きの私には堪りません。
前回作成したソリューションをさっそく開いてください。そして、WPFアプリケーションプロジェクトを右クリック→追加→新規アイテムしてください。テンプレートの一覧が表示されますね。ずっと探していくと、“Preprocessed Text Template”というテンプレートがあります。


Preprocessed Text Template


見つけられましたか?このテンプレートを選択してT4 Templateファイルを作成します。名前はPreTextTemplateRule.ttとしておきます。このファイルには、なんと!、コードビハインドファイル(PreTextTemplateRule.tt.cs)が自動的に作成されているんですねぇ。


VS2008までのT4 Templateは、プログラミングの中で変換を起動するには、結構面倒くさいコードが必要だったのですが、このCSファイルに変換を実行する為のメソッド(TransformText)をはじめとして必要なコードが全て自動生成されているんです。超便利です。


Preprocessed Text Template Code Behind
このCSファイルの中に、ファイル名と同じ名前のクラスが作成されています。このCSファイルは、T4テンプレートの記述を変えると、自動的に再生成されるようになっています。C#にはPartialクラスという便利な機能があるので、自動生成されているCSファイルに手を入れなくても、このクラスを拡張できちゃうんです。先ずは、C#ファイルを一個作成(名前はPreTextTemplateRuleCode.csとしておきましょう)します。そして、以下のようなPatialクラスを定義します。






using Microsoft.VisualStudio.ArchitectureTools.Extensibility;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;


namespace WpfApplModelAccess
{
    partial class PreTextTemplateRule : PreTextTemplateRuleBase
    {
        private IModelStore m_ModelStore;
        public PreTextTemplateRule(IModelStore modelStore)
        {
            m_ModelStore = modelStore;
        }
    }
}


これで、T4テンプレートの中から、UMLモデルが見れるようになります。


Partial Classって、やっぱり凄いです。この機能がないと、GoFの一人のJohn Vlissidesの本に書いてあった、“Generation Gap”のお世話になる必要があって、コード量も増えてしまいます(実は、Preprocessed Text Templateを新規作成したときにできるコードビハインドC#コードでは、このパターンが使われているようですが)。
で、T4テンプレートの変換をプログラムで実行するには、以下のようにプログラムを書きます。






IModelStore modelStore = ...
PreTextTemplateRule pttr = new PreTextTemplateRule(modelStore);
String result = pttr.TransformText();


これで終わりです。resultに生成されたテキストが格納されるので、これをファイルに流し込めば、一丁上がりです。


次に、T4ファイルに以下の記述を加えます。






<#@ template language="C#" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="Microsoft.VisualStudio.Uml.Classes" #>
<#@ import namespace="Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml" #>


T4ファイルでは、<# .. #>で囲まれた部分が変換の制御に関する記述です。一番最初の行で変換制御に関する記述はC#で記述されているよ~、という宣言です。2行目以下の<#@ import namespace=... #>は、C#プログラムの using namespaceと同義です。変換制御の部分は、C#コードに変換される(コードビハインドに流し込まれる)ので、変換制御コードで利用するクラスのnamespaceを一通り列挙する必要があります。


次に、T4ファイルに以下の記述を加えます。






<# foreach (IClass umlClass in m_ModelStore.AllInstances<IClass>()) { #>
  あなたはどなた?
  わたしは、<#= umlClass.Name #>です。

<# } #>


<# .. #>の中身は、C#のコードそのものです。何でも記述可能です。何をやっているか、見ればわかりますよね。
そして、<#= ... #>の部分が、変換を起動したときに、C#のコードが評価されて、テキストに置き換わる部分です。この部分では、オブジェクトのプロパティでも、メソッドコールでもテキストを返すものであれば、何でも記述できます。


前回のTargetModelに対して、これを実行すると、






  あなたはどなた?
  わたしは、Class1です。


  あなたはどなた?
  わたしは、Class2です。


  あなたはどなた?
  わたしは、Class3です。


というテキストが生成されます。TargetModel側のUMLクラス図に、クラスを追加したり、T4 Templateの内容を書き換えて、テキストとして生成する内容を変えたり、色々と試してみてください。


はい、基本説明は、これでおしまいです。読者の中には、「ふ~ん、で?何?」と思っている方もいるかな。Visual Studioは(特に)Managed Code開発には豊富な開発者支援機能を持っているので、ここに書いたような変換機能の必要性が低いのですが、VC++ Native Codeや、Windows Platformではない組込み機器向け制御ソフトウェア向けのC、C++、AssemblerをVisual Studioで開発したいときには、非常に威力を発揮する機能なんですねぇ。何せそういうプログラムは、お約束、呪文のようなコードが山ほど必要ですから。Managedの場合でも、プロジェクトのイテレーションが終わった段階でパターン化した設計を抽出して、固定的な部分はテンプレートにしてしまい、Visual Studioのプロジェクトテンプレートや、ソリューションテンプレートに組み込む、MEFを使ってIDEを拡張していく、といった応用例が考えられます。


次回以降は、UMLクラスから、C++のプログラムを生成する方法や、変換を使った高度な技、生成したファイルのプロジェクトへの登録等々を順次説明の予定です。

Comments (0)

Skip to main content