Understanding T4: <#@ include #> directive


Here is how MSDN documentation defines the include directive.

The include directive processes text from the specified file as if that text were included verbatim in the template currently being processed. In the following example, the name of the directive is include, the parameter name is file, and the parameter value is C:\test.txt: <#@ include file="c:\test.txt" #>

Syntax

<#@ include file="Included.tt" #>

file

File parameter specifies the template file T4 will merge with the contents of the main template. Included file can contain any of the T4 constructs - text blocks, code blocks, processing directives.

If file contains absolute (rooted) path, T4 will try to load the included file directly from the specified location. If file contains a relative path, T4 will determine absolute path to the included file by combining the specified relative path with the absolute path of the main template.

Although the included template may also contain an include directive pointing to a third template, T4 will continue resolving relative paths based on the absolute path of the main template. In other words, T4 does not support relative path references in nested templates. For example, T4 produces "Failed to resolve include text for file:SubFolder\Included2.tt" error when transforming Template.tt.

Templates with nested include directives

Template.tt
<#@ include file="Folder\Included.tt" #>
Template.tt
Folder\Included.tt
<#@ include file="SubFolder\Included2.tt" #>
Included2.tt
Folder\SubFolder\Included2.tt
Included2.tt

Under the hood

Example below contains two templates with text blocks, statement blocks and class feature blocks. One of the templates contains an include directive pointing to the other template. Compiled Template shows the resulting TextTransformation generated by T4.

Template
<#@ template language="C#" #>
Template Text Block 1
<#
    this.IncludedMethod();
    this.TemplateMethod();
#>
Template Text Block 2
<#@ include file="IncludedFile.tt" #>
Template Text Block 3
<#+
    void TemplateMethod()
    {
#>
Template Method
<#+
    }
#>
Include File
Included Text Block 1
<# this.WriteLine("Included statement block"); #>
Included Text Block 2
<#+
    void IncludedMethod()
    {
#>
Included method
<#+
    }
#>
Compiled Template
using System;
using Microsoft.VisualStudio.TextTemplating;  

namespace Microsoft.VisualStudio.TextTemplatingEC68E1517B8101433
{
    public class GeneratedTextTransformation: TextTransformation
    {
        public override string TransformText()
        {
            this.Write("Template Text Block 1\r\n");
            this.IncludedMethod();
            this.TemplateMethod();
            this.Write("Template Text Block 2\r\n");
            this.Write("Included Text Block 1\r\n");
            this.WriteLine("Included statement block");
            this.Write("Included Text Block 2\r\n");
            this.Write("\r\nTemplate Text Block 3\r\n");
            return this.GenerationEnvironment.ToString();
        }  

        void TemplateMethod()
        {
            this.Write("Template Method\r\n");
        }  

        void IncludedMethod()
        {
            this.Write("Included method\r\n");
        }
    }
}
Output
Template Text Block 1
Included method
Template Method
Template Text Block 2
Included Text Block 1
Included statement block
Included Text Block 2
Template Text Block 3

Notice that T4 did not simply insert the text of the included file into the template. It merged their contents, combined text and statement blocks to generate the TransformText method and used class feature blocks from both files to generate helper methods.

Host-specific features

In addition to using location of the main template to resolve relative file references, T4 allows you to specify additional directories for included files. How you do this depends on the T4 host you are using to transform the template.

Visual Studio T4 Host

T4 engine host integrated as custom tool in Visual Studio allows you to specify additional include directories in registry. Here is what it contains by default:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\TextTemplating\IncludeFolders\.tt]
Include0="C:\Program Files\Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Tools\DSLTools\TextTemplates"

In the registry path, 9.0 refers to the Visual Studio version number, which can be 8.0 for Visual Studio 2005. .tt is the extension of the template file to which the paths will apply. T4 will not search .tt include paths when transforming a template file with other extensions, such as .t4.

You can add a path to your own directory with included templates to this list by adding a new registry value to this key. For example:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\TextTemplating\IncludeFolders\.tt]
Include0="C:\Program Files\Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Tools\DSLTools\TextTemplates"
Include1="C:\My T4 Templates"

T4 will search the directories in the alphabetical order of their value names. In other words, it will look in the "Include0" directory before looking in the "Include1" directory.

Command Line T4 Host

Command line T4 host (TextTransform.exe) allows you to specify a directory to search for included templates using -I parameter.

TextTransform.exe -I "C:\My T4 Templates" Template.tt

About T4

T4 (Text Template Transformation Toolkit) is a template-based code generation engine. It is available in Visual Studio 2008 and as a download in DSL and GAT toolkits for Visual Studio 2005. T4 engine allows you to use ASP.NET-like template syntax to generate C#, T-SQL, XML or any other text files.

Ready for more? Read about <#@ property #> directive or go back to the overview for more information and examples.

Information and Links

Join the fray by commenting, tracking what others have to say, or linking to it from your blog.


Other Posts
How to use T4 to generate strongly-typed navigation class in ASP.NET
Understanding T4: <#@ assembly #> directive

Write a Comment

Take a moment to comment and tell us what you think. Some basic HTML is allowed for formatting.

Reader Comments

Added a link to new article for people reading cover to cover - <#@ property #> directive