Monthly Archives: August 2009

Using Preprocessed Text Templates

In order to explore Preprocessed Text Templates a bit further, this post shows a small example using this new feature in a simple code generator. The basic ideia is to:

  1. Create a “generic” code generation project that transforms a list of customers (the model) into a comma-separated text file, using preprocessed text templates.
  2. Create a test project that enables viewing the transformation results.

Step 1: Create the Code Generator project

Run VS2010, select File | New | Project. Select Visual C# | Class Library and name the project CustomerCodeGenerator.

Step 2: Add the model class

Rename Class1.cs to Customer.cs. Add 3 public properties of type string: Name, Address and Phone.

namespace CustomerCodeGenerator
{
    public class Customer
    {
        public string Name
        {
            get;
            set;
        }

        public string Address
        {
            get;
            set;
        }

        public string Phone
        {
            get;
            set;
        }
    }
}

Step 3: Add the template

Add a new preprocessed text template. Name the file CustomerCSVGenerator.tt. Add a new class, name the file CustomerCSVGeneratorCustom.cs. Edit the file and set the class to partial and change it’s name to CustomerCSVGenerator. This is where the model will be set for the code generator – a list of customers.

using System.Collections.Generic;

namespace CustomerCodeGenerator
{
    public partial class CustomerCSVGenerator
    {
        public List<Customer> Customers
        {
            get;
            set;
        }
    }
}

Step 4: Add the template code

The template code is quite simple, generate a single comma-separated line for each customer in the list.

<#@ template language="C#" #>
<#
foreach (Customer customer in this.Customers)
{
#>
<#= customer.Name #>;<#= customer.Address #>;<#= customer.Phone #>
<#
}
#>

Step 5: Add the test project

Select File | Add | New Project. Select Visual C# | Class Library and name the project CustomerCodeGeneratorTest. Add a reference to the CustomerCodeGenerator project.

What’s the best way of quickly viewing the transformation results? A Text Template, of course!

Add a new Text Template named CustomerCodeGeneratorTest.tt. We will use this template to call the transformation class and view the generated output.

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="CustomerCodeGenerator.dll" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="CustomerCodeGenerator" #>
<#@ output extension=".txt" #>
<#
List<Customer> customers = new List<Customer>();

customers.Add(new Customer { Name = "Customer1", Address = "Some Street", Phone="123" });
customers.Add(new Customer { Name = "Customer2", Address = "Some Other Street", Phone = "456" });
customers.Add(new Customer { Name = "Customer3", Address = "Yet Another Street", Phone = "789" });

CustomerCSVGenerator generator = new CustomerCSVGenerator();
generator.Customers = customers;
#>
<#= generator.TransformText() #>

Generated output:

Customer1;Some Street;123
Customer2;Some Other Street;456
Customer3;Yet Another Street;789

Conclusions

This is something that could be achieved with standard templates, by using includes or some other mechanism. However, preprocessed text templates enable a simple and clear way to implement code generators.

  1. The model can be anything. In this example, a Customer class defines a model that the template “knows”. We can easily read customers from a database, a XML file or some other source and reuse the same code generation class.
  2. Having the template as a class means that it is not necessary to use TextTransform.exe to automate running the transformations. This way, creating your own transformation tool is quite simple.

The next step is to see how these templates integrate with DSL Models.

Cool in VS2010 Beta1: Preprocessed Text Templates

This is a very cool feature in Visual Studio 2010. You are now able to transform a Text Template into a partial class that can be easily integrated into another component and extended.
Basically, you get the transformation class that was compiled into the temporary assembly, with all the necessary dependencies. Being a partial class, it can be extended by writing a custom class with additional properties. The transformation process, as usual, is triggered by calling the TransformText() method.

There are a few questions I would like to see answered, and may very well be the subject of future posts:

  1. As described in the previous post, a model can be anything. How does this help in creating templates that read some kind of model?
  2. Does this mean we don’t need TextTransform.exe any more? Can I build my own transformation tool?
  3. How is all this related to DSL Tools?

Resources (@ Pablo Galiano’s blog):

VS10 Beta 1 / T4 Preprocessing part 1
VS10 Beta 1 / T4 Preprocessing part 2