Syntax of T4 Templates

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies.
This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

A T4 template consists of declarations, enclosed in <#@...#> angle brackets, followed by a sequence of text stings and scriptlets. Scriptlets are fragments of C# or Visual Basic contained in <#= …#> or <#+ …#> angle brackets. T4 templates follow the following overall syntax:

  1. A declaration of the language used by the scriptlets. All scriptlets in a template must be written in the same language.
  2. A sequence of so called “property processor” declarations that define template properties use to pass parameters to the template.
  3. A series of arbitrary text strings and scriptlets. The scriptlets are interspersed with the text, with scriptlets used to dynamically generate specific text as defined by the scriptlet expression.
  4. A sequence of declarations of template-specific methods. These methods can be called from scriptlets within the template.

You should use the reusable library action called TextTemplateAction.cs to unfold T4 templates. This action, together with the Recipe Framework, allows you to pass recipe arguments to the template and receive the resulting string. This is illustrated by the example below..

The following T4 template generates a C# class that writes the same “Hello iteration:” line a number of times specified as one of the arguments.

<#@ template language="C#" #>
<#@ assembly name=”System.dll” #>
<#@ property processor="PropertyProcessor" name="ClassName" #>
<#@ property processor="PropertyProcessor" name="TargetNamespace" #>
<#@ property processor="PropertyProcessor" name="InputValue" #>
<#@ property processor="PropertyProcessor" name="Iterations" #>
#region info
// This file contains the implementation of the <#= this.ClassName #>
// class and was generated from a T4 template. 
#endregion info

// This value is passed as input without a property: <#= this.InputValue #>

using System;
using System.Text;

namespace <#= this.TargetNamespace #>
{
  /// <summary>
  /// The code in this class uses a for loop to generate multiple lines of code.
  /// </summary>
  public class <#= this.ClassName #>
  {
    public void Repeat()
    {
<# int count = this.Iterations; //note that the property is emited strong-typed
for (int i = 0; i < count; i++) { #>
      Console.WriteLine("Hello iteration: " + <#= i #>);
<# } #>
    }
  }
}

The template receives four arguments defined by the four property processor declarations. The PropertyProcessor is the name of a Recipe Framework library class that passes recipe arguments and action attributes to the template.

<#@ property processor="PropertyProcessor" name="ClassName" #>
<#@ property processor="PropertyProcessor" name="TargetNamespace" #>
<#@ property processor="PropertyProcessor" name="InputValue" #>
<#@ property processor="PropertyProcessor" name="Iterations" #>

Inside the template the argument values can be writing expressions that refer to template properties. For example the following expression obtains the value of the ClassName argument.

<#= this.ClassName #>

The following is the declaration of the action that unfolds the above template.

<Action Name="GenerateClass" Type="Microsoft.Practices.RecipeFramework.Library.Actions.Templates.TextTemplateAction, Microsoft.Practices.RecipeFramework.Library"
  Template="Text\Repeating.cs.t4" 
  InputValue="Configured Static Value">
  <!-- InputValue shows a configured attribute in T4 template that doesn't need a property on the class -->
  <Input Name="ClassName" RecipeArgument="ClassName" />
  <Input Name="TargetNamespace" RecipeArgument="TargetNamespace" />
  <Input Name="Iterations" RecipeArgument="Iterations" />
  <Output Name="Content" />
</Action>

It is worth noting that values can be passed to a template in two ways:

  • A recipe argument value can be passed to the template using the <Input …> XML element.
  • You can define an attribute of the action and assign a string value to it, and that value will be passed to the template under the name of the attribute. This is exemplified by InputValue attribute of the action (see the matching property processor directive).

Note


The <#@ assembly name="System.dll" #> reference to the System assembly is required at the beginning of each template.
The T4 templates should be saved with an extension *.cs.t4.
If you want to create template-specific methods, their declarations should go at the end of the templates enclosed in the <#+ ... #> brackets, as shown in the following example:
<#+ public string SayHello() {return "Hallo";} #>
The T4 engine does not convert Null arguments values to spaces. This means that you should handle parameters that can receive Null values yourself. The proposed approach is to handle such cases inside a scriptlet like this:
<# if (this.myParameter == null) { #>
... text one ...
<# {
else { #>
... text two ...
<# } #>

See also

Developing T4 Templates