Part 3: Rev up your code with T4

Did you know that you have a code generator in Visual Studio? In this third part of the series, we talk about using T4 to generate ANYTHING that centers around building applications.

Written by Jonathan "JD" Danylko • Last Updated: • MVC •
Creating code at the speed of T4

I remember way back when I used to write code generators to speed up my development. There were patterns of code I could create spit out immediately to write 80% of what I needed for each application.

My first exposure to T4 was when Visual Studio 2010 came out. I heard a rumor about a code generator in the IDE. I started looking into it and found out that I didn't need any third-party code generation tools.

Yes, there are other bells and whistles with some of the newer generators, but T4 was sufficient enough for me to build websites at the speed of thought.

So now, I want to show you the power and creativity of T4 and how you can maximize your development using the T4 Toolkit.

What is T4?

T4 (Microsoft, Wikipedia) was introduced back in 2005 with Visual Studio 2005. T4 stands for Text Template Transformation Toolkit and is a simple text file that is usually denoted with the '.tt' extension. It's super simple to use: Open that file in Visual Studio, make your changes to the template, and your new generated code will appear underneath it.

ASP.NET MVC uses T4 extensively when building out controllers and views. We won't be re-inventing the wheel here, but I just wanted to make you aware that T4 is not going away anytime soon.

NOTE: I would also recommend that you download the Tangible T4 Editor extension for Visual Studio. Visual Studio doesn't support the color coding of the .tt extension. If you don't like Tangible T4 Editor, find an extension that color codes your output. Trust me...it will save your sanity! Install this extension and you should be good to go.

So enough talk about T4. Let's see some code!

A Simple Example

T4 is so common now that it was added to the list of new items under File > Add > New Item.

It's under the General category as Text Template.

Create new T4 template

First, create a new directory called GeneratedClasses to keep your generated code in one location. Then, create a new Text Template and call your new file ClassBuilder.

You now have a rockin' T4 template! Woo hoo!!

GeneratedClasses\ClassBuilder.tt

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".txt" #>

Yeah...I know. Not very exciting, is it? Let's fix that!

Let's make a useful example and let T4 generate a list of tables from our database.

GeneratedClasses\ClassBuilder.tt

<#@ template language="C#" debug="True" hostspecific="True" #>
<#@ output extension=".txt" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Data" #>
<#
    string connectionString = "Server=localhost;Database=MyWebSite;Trusted_Connection=true"; 
    SqlConnection conn = new SqlConnection(connectionString); 
    conn.Open(); 
    DataTable schema = conn.GetSchema("TABLES"); 
            
    foreach(DataRow row in schema.Rows)
{ #>
<#= row["TABLE_NAME"].ToString().Trim('s')#>
 <# } #>

Some of this code should look somewhat familiar to us dot-netters. Opening a connection, getting a list of tables, and looping through the list and outputting the list into a file.

When you paste this into your ClassBuilder.tt file and hit Ctrl-S (and optionally say 'Expecto Patronum'), you'll notice that you have a newly-generated ClassBuilder.txt file that has a list of your tables. 

Wrap your head around that! Writing C# to generate C# code!

Definition of the Elements

T4 Text Templates are composed of the following elements:

  • Directives (<#@ #>)
    These are the elements that control how the template is processed.

  • Text Blocks
    These are used outside of the <# #>. Anything outside of these brackets is considered output.

  • Control Blocks (<# #>)
    There are Standard Control Blocks and Expression Control Blocks.

    • Standard Control Blocks are blocks of code that can execute C# code (<# #>).
    • Expression Control Blocks are blocks of code that is immediately executed and converted to a string (<#= #>).

These are the foundations of the T4 Templating language. If you want an more in-depth discussion, I will refer you to the Writing a T4 Text Template page.

Time to Up Our Game!

Ok, you know what I hate doing when building an application? I hate building out every single repository for every table. Let's make a T4 to generate repositories for us. I just want a jumpstart to building out my repositories.

We'll use the Repository class from our ThinController example a couple weeks ago and create inherited repositories from that.

Here is the final result we expanded on from our sample above.

GeneratedClasses\ClassBuilder.tt

<#@ template language="C#" debug="True" hostspecific="True" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Data" #>
<#
    string myNameSpace = "Put.Your.Namespace.Here";
    string contextName = "BlogContext";
#>
using System;
namespace <#= myNameSpace #><#
    string connectionString = "Server=localhost;Database=myOwnDatabase;Trusted_Connection=true"; 
    SqlConnection conn = new SqlConnection(connectionString); 
    conn.Open(); 
    DataTable schema = conn.GetSchema("TABLES"); 
            
    foreach(System.Data.DataRow row in schema.Rows)
    {
        var tableName = row["TABLE_NAME"].ToString();
        var className = string.Format("{0}Repository", tableName.Trim('s'));
 #> 
    public class <#= className #>: Repository<<#= tableName.Trim('s'#>>
    {
#region Constructors
        public <#= className #>(DbContext context) : base(context) { }
        public <#= className #>() : base(new <#= contextName #>()) { }
        #endregion
        public IEnumerable<<#= tableName.Trim('s'#>> LoadAll()
        {
            return base.GetAll();
        }
        public <#= tableName.Trim('s'#> GetById(string id)
        {
            return First(e => e.Id == id);
        }
}
 <# } #>
 
}

Phew! Did you see all of those repository classes that we generated with 2 keystrokes? Now THAT is coding. :-)

A couple of things to note:

  • We changed the output extension to .cs since we were writing out C# classes. You can change this to any extension...even .CSV.
  • When you are inside the blocks, you can basically issue any command so long as you have the correct assembly "import"-ed.
  • TRY to keep your curly brackets as clean and as indented as you can. It can get messy REALLLLY quick!

You can easily expand upon these examples, build your library, and generate close to 60-80% of an application from scratch in no time at all.

Conclusion

As you can see, you can create a number of templates for generating SQL statements, XML, C# code, and yes, even VB code. The possibilities are endless as to what you can generate.

In the next part of this series, we'll talk about two of my favorite tools: JetBrains' ReSharper and DevArts' SQL Complete. Both complement each other in assisting with your coding, whether it be C# or SQL!

Series: How to take your ASP.NET MVC development to ludicrous speeds.

  1. Transforming XML/JSON/CSV into Classes
  2. Use pre-built applications
  3. T4 (Text Template Transformation Toolkit)
  4. ReSharper/SQL Complete
  5. ORM (Object Relationship Management)

Get creative and see what you can build with a T4 template to speed up your development. Post your ideas below!

Did you like this content? Show your support by buying me a coffee.

Buy me a coffee  Buy me a coffee
Picture of Jonathan "JD" Danylko

Jonathan Danylko is a web architect and entrepreneur who's been programming for over 25 years. He's developed websites for small, medium, and Fortune 500 companies since 1996.

He currently works at Insight Enterprises as an Principal Software Engineer Architect.

When asked what he likes to do in his spare time, he replies, "I like to write and I like to code. I also like to write about code."

comments powered by Disqus