Software Development

Code concepts: Visual Studio's T4 templates

The T4 templating system is used to programmatically generate artifacts. Here's an overview about why the templates are useful and how to work with them.

 

One of the least publicized features of Visual Studio is the T4 templating system, which is used to programmatically generate artifacts (almost always code files). Over the last six months or so, there has been a lot more awareness of the T4 system. This tool can be very useful in removing the drudgery from common code tasks without needing a third-party tool.

In this edition of Code concepts, I'll explain what T4 templates are, why you should look into them, and the basics of working with them.

What are T4 templates?

T4 stands for Text Template Transformation Toolkit. A T4 template is a text file with a .tt extension in a Visual Studio project. The T4 template is put through the T4 engine whenever you switch to another file in the code editor. The engine reads the file, processes the commands within the file, and outputs a text file with the T4 template generating the contents. If the resulting file is a code file, it is compiled with the rest of the project.

How is the useful?

For better or for worse, many .NET projects end up with piles of cookie-cutter code. It might be data access code, XML files, or any other number of repetitive pieces of text. With the T4 templating system, you can automate the creation of those files, which saves time and ensures that the files are creating accurately.

Also, the T4 templating system can allow for a more direct link between business logic and the code in some scenarios.

How do you work with the templates?

On the surface, T4 templates resemble classic ASP or PHP pages; the templates are plain text files with various directives inserted into them. Anything outside of the directives is placed in the output stream, and the code within the directives controls the flow and can write to the output stream. You can use either VB.NET or C# as the processing language within the template. I hope that in Visual Studio 2010, F#, IronRuby, and IronPython could be used as well, as I consider all three to be great candidates for this task.

To create a T4 template, you add a new item to your project. You won't see a T4 template on the list though; you need to add it as a "Text File" and give the file an extension of .tt After it is created, you will see that, in addition to the T4 template, there will be a sub-file with the same name but an extension of either .cs or .vb, depending on if your project is a C# or VB.NET project; this is the destination for the template's output. If you want to change the name of the output file, you can use a directive in the template to change it.

Once you create the template, you can start filling it in. In my experiments, it looks like T4 templates default to using C# as the language for processing directives even in a VB.NET project. All the same, it is a good idea to specify a language using this directive as the first line in the template:

<#@ template language="C#" #>

You can change "C#" to "VB" if you want to write your directives in VB.NET. Any text in the template will be directed to the output as is. Directives are inserted inside of blocks that start with "<#" and end with "#>". Blocks that contain T4 instructions (like the template instruction shown above) start with @ (an at symbol) at the beginning of the directive. In addition, you can use "<#= #>" to output the return value of the code within the directive. Otherwise, like PHP or other similar systems, you put code within the <# #> symbols. Here are three examples.

Example 1
<#@ template language="C#" #>

Is 1 greater than 0?

<# if (1 > 0) { #>

It's true!

<# } else { #>

It's not true!

<# } #>

Would produce:

Is 1 greater than 0?
It's true!
Example 2
<#@ template language="C#" #>

Is 1 greater than 0?

<# if (1 > 0) {

this.Write("It's true!");

} else {

this.Write("It's not true!");

} #>

Would produce:

Is 1 greater than 0?
It's true!
Example 3
<#@ template language="C#" #>

When was this template compiled?

Right... NOW: <#= DateTime.Now.ToString() #>

Would produce:

When was this template compiled?
Right... NOW: 10/17/2009 12:49:03 AM

Drawbacks to T4 templates

The drawbacks to T4 templates include the following:

  • Visual Studio 2005 does not support T4 templates without the DSL and GAT toolkits.
  • Visual Studio does not natively perform highlighting, IntelliSense, etc. There are tools out there to correct this, such as Clarius Visual T4 and Tangible Engineering's T4 Editor.
  • You are limited to VB.NET or C#, neither of which are particularly expressive for this kind of work. Lisp/Scheme, Ruby, Python, and especially Perl would all be better languages for this task.

Summary

There is a lot more to cover about T4 templates. In the near future, I will combine T4 templates and many of the other Code Concepts articles into a parser and rules engine, so stay tuned!

In the meantime, I suggest you check out Oleg Sych's excellent information on the topic, as well as the MSDN documentation for more information about T4 templates.

J.Ja

Disclosure of Justin's industry affiliations: Justin James has a contract with Spiceworks to write product buying guides. He is also under contract to OpenAmplify, which is owned by Hapax, to write a series of blogs, tutorials, and other articles.

-----------------------------------------------------------------------------------

Get weekly development tips in your inbox Keep your developer skills sharp by signing up for TechRepublic's free Web Developer newsletter, delivered each Tuesday. Automatically subscribe today!

About

Justin James is the Lead Architect for Conigent.

2 comments
Justin James
Justin James

Are T4 templates something that you think you could use in your projects? What kinds of uses do you see for them? J.Ja

tracy
tracy

Hi Justin, Good to see a blog again on T4 templating. I started using these about a year ago to take away some of the mundane tasks associated with proper pattern development for backend systems. Since that time I have developed several useful DSL files that I use T4 to create. These include a Database DSL which creates my DDL scripts and stored procedures, a data repository DSL that handles my ORM for data transfer objects, a business object DSL that creates a composite object model for combing DSL files into a more useful business object, and finally, a service DSL that creates a service model with REST to expose the ORM heirarchy to the UI. I read/create all of the DSL files with T4 Templates. So when I am done I have a number of artifacts that would require a lot of boredom to produce such as interfaces (read and write), controllers, entities, etc. My development also includes a 100% code coverage of unit testing modules to be sure that everything works. Now that I have written a disertation the short answer is "Yes, I use T4 and do not know what I would do without it!".