Intro to T4 Templates: Generating Text in a Hurry
Editorial Note: I originally wrote this post for the SubMain blog. You can check out the original here, at their site. While you’re there, take a look at GhostDoc. In addition to comment generation capabilities, you can also effortlessly produce help documentation.
Today, I’d like to tackle a subject that inspires ambivalence in me. Specifically, I mean the subject of automated text generation (including a common, specific flavor: code generation).
If you haven’t encountered this before, consider a common example. When you file->new->(console) project, Visual Studio generates a Program.cs file. This file contains standard includes, a program class, and a public static void method called “Main.” Conceptually, you just triggered text (and code) generation.
Many schemes exist for doing this. Really, you just need a templating scheme and some kind of processing engine to make it happen. Think of ASP MVC, for instance. You write markup sprinkled with interpreted variables (i.e. Razor), and your controller object processes that and spits out pure HTML to return as the response. PHP and other server side scripting constructs operate this way and so do code/text generators.
However, I’d like to narrow the focus to a specific case: T4 templates. You can use this powerful construct to generate all manner of text. But use discretion, because you can also use this powerful construct to make a huge mess. I wrote a post about the potential perils some years back, but suffice it to say that you should take care not to automate and speed up copy and paste programming. Make sure your case for use makes sense.
The Very Basics
With the obligatory disclaimer out of the way, let’s get down to brass tacks. I’ll offer a lightning fast getting started primer.
Open some kind of playpen project in Visual Studio, and add a new item. You can find the item in question under the “General” heading as “Text Template.”
Give it a name. For instance, I called mine “sample” while writing this post. Once you do that, you will see it show up in the root directory of your project as Sample.tt. Here is the text that it contains.
<#@ 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" #>
Save this file. When you do so, Visual Studio will prompt you with a message about potentially harming your computer, so something must be happening behind the scenes, right? Indeed, something has happened. You have generated the output of the T4 generation process. And you can see it by expanding the caret next to your Sample.tt file as shown here.
If you open the Sample.txt file, however, you will find it empty. That’s because we haven’t done anything interesting yet. Add a new line with the text “hello world” to the bottom of the Sample.tt file and then save. (And feel free to get rid of that message about harming your computer by opting out, if you want). You will now see a new Sample.txt file containing the words “hello world.”
Beyond the Trivial
While you might find it satisfying to get going, what we’ve done so far could be accomplished with file copy. Let’s take advantage of T4 templating in earnest. First up, observe what happens when you change the output extension. Make it something like .blah and observe that saving results in Sample.blah. As you can see, there’s more going on than simple text duplication. But let’s do something more interesting.
Update your Sample.tt file to contain the following text and then click save.
<#@ 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" #> <# for(int i = 0; i < 10; i++) WriteLine($"Hello World {i}"); #>
When you open Sample.txt, you will see the following.
Hello World 0 Hello World 1 Hello World 2 Hello World 3 Hello World 4 Hello World 5 Hello World 6 Hello World 7 Hello World 8 Hello World 9
Pretty neat, huh? You’ve used the <# #> tokens to surround first class C# that you can use to generate text. I imagine you can see the potential here.
Oh, and what happens when you type malformed C#? Remove the semicolon and see for yourself. Yes, Visual Studio offers you feedback about bad T4 template files.
Use Cases
I’ll stop here with the T4 tutorial. After all, I aimed only to provide an introduction. And I think that part of any true introduction involves explaining where and how the subject might prove useful to readers. So where do people reasonably use these things?
Perhaps the most common usage scenario pertains to ORMs and the so-called impedance mismatch problem. People create code generation schemes that examine databases and spit out source code that matches with them. This approach spares the significant performance hit of some kind of runtime scheme for figuring this out, but without forcing tedious typing on dev teams. Entity Framework makes use of T4 templates.
I have seen other uses as well, however. Perhaps your organization puts involved XML configuration files into any new projects and you want to generate these without copy and paste. Or, perhaps you need to replace an expensive reflection/runtime scheme for performance reasons. Maybe you have a good bit of layering boilerplate and object mapping to do. Really, the sky is the limit here, but always bear in mind the caveat that I offered at the beginning of this post. Take care not to let code/text generation be a crutch for cranking out anti-patterns more rapidly.
The Ghost Doc Use Case
I will close by offering a tie-in with the GhostDoc offering as the final use case. If you use GhostDoc to generate comments for methods and types in your codebase, you should know that you can customize the default generations using T4 templates. (As an aside, I consider this a perfect use case for templating — a software vendor offering a product to developers that assists them with writing code.)
If you open GhostDoc’s options pane and navigate to “Rules” you will see the following screen. Double clicking any of the templates will give you the option to edit them, customizing as you see fit.
You can thus do simple things, like adding some copyright boilerplate, for instance. Or you could really dive into the weeds of the commenting engine to customize to your heart’s content (be careful here, though). You can exert a great deal of control.
T4 templates offer you power and can make your life easier when used judiciously. They’re definitely a tool worth having in your tool belt. And, if you make use of GhostDoc, this is doubly true.
Code Generation has been around for a while. Personally if I were to learn a code generation tool it wouldn’t be T4, I’d go with CodeSmith or even MyGeneration.
I’m not familiar with those — what do they earn you? (I’m not a huge fan of using these to generate code in the first place, but learning T4 would give you advanced knowledge of using things like EF and Ghostdoc)