T4 Toolbox: Automatic Template Transformation


By default in T4, the code generation (a.k.a. template transformation) occurs when you save a template (.tt) file or select Run Custom Tool from its context menu in Solution Explorer. This works very well while you are actively developing the code generator, making changes in the template file and saving it to see the generated code. However, once development of the code generator itself is finished and your entire development team begins using it, this way of triggering code generation becomes less than ideal.

If your template generates code from metadata stored in a separate file, such as the LINQ to SQL .dbml file, it is easy for a developer to change the input file and forget to regenerate the code using the code generator in a separate T4 file. This mistake can lead to unnecessary frustration and wasted effort, especially when a T4-based code generator replaces a built-in code generator, such as MSLinqToSqlGenerator, which generates code automatically whenever the input file is saved.

You can eliminate the waste of effort and frustration by triggering your T4-based code generator automatically, whenever the input file is saved. This can be accomplished using a proven Visual Studio extensibility mechanism – Custom Tools. In this article, we will review how you can create your own custom tool or simply use the one provided by the T4 Toolbox.

Custom Tools

A custom tool - sometimes referred to as a single file generator - can be used to extend the Visual Basic, Visual C#, and Visual J# project systems in Visual Studio. A custom tool is a COM component that implements the IVsSingleFileGenerator interface. Using this interface, a custom tool transforms a single input file into a single output file. The result of the transformation may be source code, or any other output that is required. T4 itself provides a custom tool called TextTemplatingFileGenerator, which is automatically associated with .tt files and performs template transformation. Before you can use a custom tool, you must register it with the system or in the Visual Studio local registry. You can find complete details about custom tools and single file generators in Visual Studio SDK.

T4-Based Custom Tool

One way to automate T4-based code generation, is to create a custom tool that will be associated with your input file. When the input file is modified, Visual Studio will invoke this custom tool; the tool will load a T4 template either from an embedded resource or an external file and use ITextTemplating service to generate the code.

There are different ways to implement such custom tool. If you are building a modeling solution using Domain-Specific Language tools, Jean-Mark Prieur provides an excellent example in Part 4 of the DSL Tools Lab. Alternatively, you can follow instructions in Visual Studio SDK, which requires more work, but does not have a dependency on DSL toolkit. Either way, you will want to take advantage of the built-in functionality provided by T4 and inherit your custom tool from the TemplatedCodeGenerator as Jean-Mark suggests.

Although implementing a T4-based custom tool is not difficult, the custom tool requires registration, which means having an installation program. If you are a tool developer, this is not a problem – you probably already have one. If you are an application developer, this is just another bit of extra work that doesn’t directly contribute to your product, the extra work you want to avoid.

T4ScriptFileGenerator

T4 Toolbox (version 9.10 or later) provides a ready-to-use custom tool called T4ScriptFileGenerator. You can associate it with a particular file using Solution Explorer and Properties window as shown below.

image image

First time you save the input file (Northwind.dbml in our example) after assigning T4ScriptFileGenerator as its Custom Tool, it will create an empty .tt file similar to this.

<#@ template language="C#" hostspecific="True" debug="True" #>
<#@ output extension="txt" #>
<#@ include file="T4Toolbox.tt" #>

Note that the new .tt file has the usual TextTemplatingFileGenerator custom tool associated with it.

image image

When you add the actual code generation logic and save this file, T4 engine will transform it automatically, as you would expect. In this example, we will modify Northwind.tt file to look like this.

<#@ template language="C#v3.5" hostspecific="True" #>
<#@ output extension="log" #>
<#@ include file="T4Toolbox.tt" #>
<#@ include file="T4Toolbox\LinqToSql.tt" #>
<#
    LinqToSqlGenerator generator = new LinqToSqlGenerator();
    generator.DbmlFile = "Northwind.dbml";
    generator.Run();
#>

Now if we go back and modify our input file, Northwind.dbml, the T4ScriptFileGenerator will reuse the existing T4 script, Northwind.tt, and trigger the code generation. In other words, the Northwind.tt file is being transformed automatically whenever we change the input file, Northwind.dbml.

This configuration process is easy to follow and once you are done, simply check your project into your source control and the custom tool configuration will be preserved in the project file itself. To begin using this code generator, other developers on your team simply need to have T4 Toolbox installed on their computers and get latest version of the project source code.

However, if you are building T4-based code generators that can be created and configured by others, perhaps your development team or external customers, you may want to save them the trouble of performing these steps manually every time they need to create a new code generator.

T4ScriptFileGeneratorWizard

T4 Toolbox (version 9.12 or later) also allows you to automatically associate T4ScriptFileGenerator with an input file using a Visual Studio Project Item Template. Simply put both the input file and the code generation script (.tt) file in the template as described in the article mentioned above and provide a VSTEMPLATE file similar to this.

<VSTemplate Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Item">
  <TemplateData>
    <DefaultName>DataClasses.dbml</DefaultName>
    <Name>LINQ to SQL Model</Name>
    <Description>LINQ to SQL entity classes and schema objects.</Description>
    <ProjectType>CSharp</ProjectType>
  </TemplateData>
  <TemplateContent>
    <References>
      <Reference><Assembly>System</Assembly></Reference>
      <Reference><Assembly>System.Core</Assembly></Reference>
      <Reference><Assembly>System.Data.Linq</Assembly></Reference>
    </References>
    <ProjectItem SubType="Designer" TargetFileName="$fileinputname$.dbml" ReplaceParameters="true">Dbml.xml</ProjectItem>
    <ProjectItem SubType="" TargetFileName="$fileinputname$.tt" ReplaceParameters="true">LinqToSqlModel.tt</ProjectItem>
  </TemplateContent>
  <WizardExtension>
    <Assembly>T4Toolbox, Version=9.11.21.1, Culture=neutral, PublicKeyToken=7e313accbcce84dc</Assembly>
    <FullClassName>T4Toolbox.VisualStudio.T4ScriptFileGeneratorWizard</FullClassName>
  </WizardExtension>
</VSTemplate>

Notice the use of <WizardExtension/> to associate the T4ScriptFileGenerationWizard with this project item template. This wizard extension will assign T4ScriptFileGenerator as a custom tool to the root item unfolded by the template - $fileinputname$.dbml or Northwind.dbml file in this example. If the project item template contains a T4 script file with the matching name ($fileinputname$.tt), the wizard extension will also make sure the code in it is preserved and used for code generation. If the project item template does not contain a T4 script file, an empty .tt file will be created instead.

Remember that T4 Toolbox has a separate assemblies for Visual Studio 2008 (T4Toolbox.dll) and Visual Studio 2010 (T4Toolbox.10.0.dll). The VSTEMPLATE example above is for Visual Studio 2008. In 2010, you have to change the <WizardExtension> to look like this.

<WizardExtension>
  <Assembly>T4Toolbox.10.0, Version=9.11.21.1, Culture=neutral, PublicKeyToken=7e313accbcce84dc</Assembly>
  <FullClassName>T4Toolbox.VisualStudio.T4ScriptFileGeneratorWizard</FullClassName>
</WizardExtension>

As you have already guessed, T4 Toolbox uses T4ScriptFileGenerator and T4ScriptFileGeneratorWizard in its LINQ to SQL model sample code generator for C#. You can see it in action yourself.

image

Conclusion

Although the built-in mechanism for triggering template transformation in T4 works well during development of a code generator, it often leads to mistakes during its normal use, when developers primarily modify the code generation model or input file. There are different ways of triggering the code generation automatically when the input file changes. In this article we discussed one of these approaches, based on Custom Tools. While it is possible to completely hide code generation from developers with this approach, doing so would prevent developers from being able to take advantage of rich template-based customization capabilities offered by T4. The T4ScriptFileGenerator in T4 Toolbox allows you get the best of both options: have the code generation occur automatically when the input file changes and still allow developers to customize the code generator by changing the T4 template.


Write a Comment

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

Reader Comments

[…] T4 Toolbox: Automatic Template Transformation (Oleg Sych) […]

[…] T4 Toolbox: Automatic Template Transformation - Oleg Sych looks at making T4 templates automatically re-generate when one of the files they are based on changes ensuring the generated output is always up to date, making use of the Visual Studio Custom Tool Support […]

Hi Oleg,

I’m trying to associate “T4ScriptFileGenerator” Custom tool with a VS 2010 native class diagram, but it simply ignores it and does not generate the .tt file.

I’m generating code from a class diagram, and I wanted it to generate when the diagram changes, but it doesn’t work to me.

Any idea?

Thanks and great post!
Sergi

Sergi,

I don’t think UML class diagrams in modeling projects of Visual Studio 2010 support custom tools. The code-based class diagrams in C# and Visual Basic projects do support them, although there is no meaningful metadata stored in the .cd files - only diagram layout. This article provides an overview of how to generate code from UML diagrams.

Oleg

Hi Oleg,

Is it possible to have 2 custom tools to run?

E.g. Resource.resx, it has a built-in custom tool ResxFileCodeGenerator. Is it possible to trigger both ResxFileCodeGenerator and T4ScriptFileGenerator?

Hi Oleg,
I’m new to T4 templates and find it very interesting but i’m having trouble trying to implement the following:

Create a template that connects to CRM web service, brings back a list of entities, then loop through each one and i use the properties to build up my template CS file.
I’d need to reference CRM sdk in my project that has the tt files, but when i try importing the namespaces or referencing the objects via code, it just gives me errors.
Can this sort of thing be done?
thanks,
Paul

Hi Oleg,

thanks for your great tutorials on T4. They helped me a lot.

But I still have one small problem: is it possible to trigger the transformation automatically when the source file is changed by an external program (Visual Studio notices the change and prompts if it should reload, etc.)?

We still have to manually save the changed input file at the moment to trigger code generation, which is easily forgotten.

Thanks again…

Fabian

I have a VS 2012 console project which generates the code files. Currently, I run the code generation script file by selecting ‘Run custom Tool’ from the context menu in VS. I wonder if I can run the script file from the Command Prompt.

T4 Toolbox does not support TextTransform.exe (the command-line T4 host) at this time.