One of the things that really bother me about T4 templates is the lack of direct parameter support (at least in the Visual Studio 2008/.NET 3 timeframe).
In an earlier post, I passed parameter by writing the parameter data to a file outside of the template and reading the data from within. I used a common assembly linked to both sides of the divide. This works for me, but it is really hacky.
GAX Template Host
During my preparation for my Portland Code Camp presentation, I came across Guidance Automation Toolkit for Visual Studio 2008. It has its own TemplateHost that includes a Dictionary of parameters.
Parameters are exposed to the Template through a custom directive. On the template, the parameter is declared using a directive like this:
<#@ property processor="PropertyProcessor" name="MyName" type="String" #>The directive contains the following parts:
processor | Should be "PropertyProcessor" (there may be a way to write your own processor, I haven’t gone down that rat hole yet). | name | The Variable name that can appear in your code. It works just like a variable, however, tangable T4 Editor doesn’t provide Intenesence (I wouldn’t have expected it). | type | Any .NET Type that the template knows about. You should use the .NET type name (as opposed to C# or VB.NET type). |
var arguments = new DictionaryTo pass parameters from your code you need to create a Dictionary<string, PropertyData>, add your parameters and pass them as the second argument into the TemplateHost constructor (the first can be any string as far as I can tell).(); arguments.Add("MyProperty", new PropertyData("String", typeof(string)));
Simple Sample
The Template
<#@ template language="C#" debug="True" #> <#@ output extension="txt" #> <#@ assembly name="System.dll" #> <#@ import namespace="System" #> <#@ property processor="PropertyProcessor" name="MyProperty" type="Nullable<Int32>"#> <#@ property processor="PropertyProcessor" name="MyName" type="String"#> My Property Test <# if (MyProperty.HasValue) {#> Property Value: <#= MyProperty.Value #>! <#}#> Name: <#= MyName #>
C# code
static void Main(string[] args) { // Prepare template parameters var arguments = new Dictionary<string, PropertyData>(); arguments.Add("MyProperty", new PropertyData(42, typeof(int?))); arguments.Add("MyName", new PropertyData("Jack Stephens", typeof(string))); // Initialize GAX template host // The Template Host is from GAX, not the default host var host = new TemplateHost("Random String", arguments); host.TemplateFile = Path.Combine(Directory.GetCurrentDirectory(), "PropertyTest.tt"); // Transform template string template = File.ReadAllText(host.TemplateFile); ITextTemplatingEngine engine = new Engine(); string output = engine.ProcessTemplate(template, host); Console.Write(output); Console.ReadKey(); }