Chapter 4. Transforming Text Templates

In This Chapter

  • Discovering where templating for Visual Studio originated

  • Figuring out when to use T4

  • Getting your environment ready for T4 use

  • Using some basic T4 directives

T4 (Text Template Transformation Toolkit) is a code generation toolkit built into Visual Studio. It is a built in language used to make the default ASP.NET and Windows Forms files in C# or VB, for example, when you use the Add New Item feature.

Scott Hanselman, from Microsoft, said it best: "Now's the time to introduce code generation to your company." I wholeheartedly agree. Code generation increases developer productivity, decreases bugs in final versions, and makes people happy.

Lars Corneliussen, a Microsoft MVP, said, "T4 in VS is the equivalent to index.php in Apache," and he isn't far from the truth. T4 is a starting point for a project, providing seamless redirection and logical formatting of what the user (in this case, the developer) actually sees. It is the template, just as the name suggests.

T4 is a big topic, like so many others in this book, but you should be able to get started creating code generation from the material here. Getting your environment ready and understanding the concepts are the most important steps.

Getting to Know T4

In this chapter, I look at T4 as a code-generation tool. It is a lot more than that. Really, it is a tool for the management of metadata around Domain Specific Languages. If that makes no sense to you, join the club.

Many things about computer science are elegant, and the current drive toward meta-programming and the use of higher and higher level languages to solve tougher and tougher problems is one of them. I am a second-generation kind of guy, though. I let the early adopters try something out first and see whether it works. If it works, then I use it.

For code generation, T4 works.

At its most complex, T4 can review information about the kind of projects you build and determine what kind of templates you need to get the job done. That's cool, but let's stick with our analysis and just let T4 do the dirty work.

Looking back at the DSL Tools

One of the first ways that Microsoft tried to implement code generation back in the day (and it is still around) was through the Environment Design Time Environment (EnvDTE), and by giving developers access to the code files themselves.

This bare-bones approach provided by EnvDTE isn't really what they were after, though. The goal of templating was to provide a language of languages, which developers could use to model their own development style. The code generation is almost secondary.

Microsoft's next shot to solving the code-generation problem was the Domain-Specific Language Tools. The idea here was to use the EnvDTE and other markup languages to describe a very high-level idea in a project — for example, a new ASPX page. Not any specific ASPX page: any ASPX page.

That description can then become the starter code that you see when you ask for a new ASPX page. See what I mean? When you describe a higher-level concept like requesting a new ASPX page, the DLS implements a concrete version, which you then can edit.

Looking ahead to what it became

To put it in REAL general terms, the DSL Tools split into two things: code generation and modeling tools. The modeling tools are Oslo and M. The code generation is T4.

Because T4 is designed to generate anything, it can emit any kind of file. If you think about it, it all makes sense. If an entity in your domain model is a product Web site, then T4 would have to emit HTML, CSS, and JavaScript when a new product is added to the database.

The same thing applies to the language that is emitted as part of the project. T4 doesn't care what code you are emitting. It just wants to stamp out what matches the model you define for it. If you set up the model to use C#, that's fine. VB? Fine. T4 is just generating and giving text an extension.

Additionally, you can write your code inside the T4 file in C# or VB.NET. This is the code that makes any decisions about the output, accesses data sources that might be needed to generate the code, and so on. It follows the same .NET rules.

Even though T4 was developed as an addition to Visual Studio 2008 and is baked into version 2010, you can use it in all previous versions back to 2005.

Figuring Out When to Use T4

Now that it is more or less clear what T4 is designed to do, the next step is figuring out when to use it. There are two main applications, as well as many lesser ones out there — the following sections are not all-inclusive. The main ones are replacing repetitive coding and building code based on outside data.

Replacing repetitive coding

Like snippets do at the class level, T4 can replace repetitive coding at the file level. If you think about it, you realize that there is a whole host of code that you shouldn't have to write over and over and over, but nonetheless you do.

Take something simple, like an HTML page. Every page must have certain elements, by the HTML 4.0 Transitional standard:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//
   EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.
   dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title></title>
</head>
<body>

</body>
</html>

Those are required elements! Can't they just be . . . assumed? As it turns out, no, they can't, because some of the elements must have data inserted inside them. This is just the starting point — exactly what T4 is good at providing.

Building code based on outside data

The more powerful use of T4 is to reference outside data to set up code templates. This can be metadata about a project like supporting files that need to be referenced, or direct data like the previous product Web site example.

Let's look at project metadata for a moment. MVC4WOF is an open source project that I participate in, and it uses metadata in the form of contract files to generate code. (Check it out at www.mvc4wpf.com.)

In a classic example of an automation pattern, MVC4WPF's New File dialog box (see Figure 4-1) checks with the user to get the contract (in the form of an interface) that is being referenced for the given Model, View, or Controller being generated.

This allows T4 to parse through the interface, grab pertinent information, and add it to the resultant file.

Selecting controller interfaces.

Figure 4-1. Selecting controller interfaces.

Setting Up the Environment

You need to know a few details relating to the environment.

Changing the security settings

You can relax the security requirements for T4. If you write T4 documents and don't sign them (which is often the case), you will receive a dialog box warning you that you might be generating some dangerous code. You can see that message in Figure 4-2.

The security setting in the Tools/Options box.

Figure 4-2. The security setting in the Tools/Options box.

Note

As T4 files are essentially macros, this warning makes sense. It is possible for someone to write malicious code and execute it on your development workstation. I advise that you turn off the security during development of the template and back on when you are back to your daily scheduled programming.

Creating a template from a text file

The simplest TT file is just a text file, edited in Notepad, with some basic commands in it called Directives. Follow these steps to create a template from that basic text file:

  1. Open Notepad.

  2. In the new file, add the following lines of code.

    <#@ output extension=".cs" #>
    
    public class TestClass
    {
    }

    The lines are cryptic, I know, but they will make sense in a second.

  3. Save the file in your Documents folder as GenerateClass.tt.

    It should look like Figure 4-3.

  4. Create a new class library in Visual Studio.

  5. Right-click on the project file, select Add, and then Existing File.

    You'll see a file selection dialog box.

    The world's simplest TT file.

    Figure 4-3. The world's simplest TT file.

  6. Select the GenerateClass.tt file you created in Step 3. You might have to select All Files from the Files of Type drop-down menu if .tt isn't one of the file types available.

  7. Click OK.

    You get the security warning discussed in the section "Changing the security settings," earlier in this chapter, shown in Figure 4-4. Click OK to that, too.

    Notice that in the file tree in Solution Explorer, under the TT file, there is now a CS file with your code in it, as shown in Figure 4-5.

    The vaunted security message.

    Figure 4-4. The vaunted security message.

    The generated code file.

    Figure 4-5. The generated code file.

Using Some of the T4 Directives

Clearly this is a very Hello World example. The magic of T4 is complex, and I had to spend a lot of time (believe it or not) making the simplest example.

One of the things that makes T4 work well are the directives built into the language. These commands are just like shell commands. They have parameters and perform certain tasks on the file.

Setting the output

The first directive you see in the example in the earlier section "Creating a template from a text file" is the output directive. I wanted a C# file, so I used the .cs extension. You could emit anything, though — text, HTML, VB, or even a custom format that you need for your project, such as

<#@ output extension=".bill" #>

Another parameter for output is Encoding, which is exactly what it sounds like. Options include

  • Default

  • ASCII

  • BigEndianUnicode

  • Unicode

  • UTF32

  • UTF7

  • UTF8

If you need to represent special characters in your files, you need to specify your encoding.

Configuring a template

Template is a directive that specifies the various properties of the T4 text itself. The goal is to affect how the parsing engine interprets the code in the template itself. The options include

  • language: This is the language for the code that does the work. You can emit anything, but the code in the template has to be VB or C#.

  • inherits: This is a class that derives from TextTransformation to be used as the base class.

  • culture: This sets the System.Globalization culture. You know, like en-US or en-GB.

  • debug: Just like the ASP.NET debugger, this sets the return of debug symbols.

  • hostspecific: This is for use with custom hosts — you'll run into it if you are writing for custom hosts.

Including includes

Includes are nice and easy.

Remember ASP classic? No, I don't mean ASP.NET pre-MVC. I mean the old ASP, with VB script, pre-.NET. This is like that. (If you don't, that's okay; I explain it in the next section.)

If you want to include the contents of a file somewhere in your template, just drop the include directive in there and the name of the file in a file attribute.

<#@ include file="c:specialsource.cs" #>

That's all there is to it.

Importing items and assemblies

The import and assembly directives assist with writing code in a template. In the example earlier in this chapter, I emitted text, but in the real examples that you find in MSDN, you write C# or VB code to modify the text.

If you want that code to use .NET Framework constructs, you need to reference the assembly and import the namespace. For instance, if you are going to get values from a file in your template, you need the System.IO library.

First you need to reference the assembly, unless you are certain the assembly will be referenced in the project. Then you should import the namespace so you don't have to reference items via fully qualified names, as like this:

<#@ assembly name="System.IO.DLL" #>
<#@ import namespace="System.IO" #>

Then, you can reference the file maintenance classes inside the code of the template. You reference code using the <# and #> statements.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.3.136