The World’s Leading Microsoft .NET Magazine
   
 
The .NET Addict's Blog

My Top Tags

                                                           

My RSS Feeds








I heart FeedBurner

Latest Diggs - Programming

Computers Blogs - Blog Top Sites

Site Hits

Total: 4,878,821
since: 19 Jan 2005

T4, Visual Studio 2008's Best Kept Secret

posted Thu 02 Apr 09

T4 is a Text Template engine that comes with Visual Studio 2008. I'm a little fuzzy on its origins and true purpose, but from the documentation that is available on MSDN, it looks as though T4 was originally conceived as the underlying plumbing that allowed DSLs (Domain-Specific Languages) to programmatically generate compileable classes on the fly.

The benefit of this engine is that it's available for code generation even if you're not working on a DSL. In fact I would go so far as to say that regardless of it's original intent, T4 probably has wider appeal among developers looking to code generate as a solution to the "boilerplate of spaghetti" problem than it does among the relative minority of people building DSLs. I'm not saying that it's less meaningful to DSL builders, I'm just saying that there are more devs who need code generation for their day-to-day tasks than there are devs who are building DSLs.

Before diving into a sample I just want to try and make it clear that T4 is a code eneration utility. It handles those situations where you cannot fix your redundant or tedious code problems with inheritance, DI, or Aspects.

One of the tasks that I do all of the time when building an application with a desktop (or Silverlight) GUI is build classes that implement INotifyPropertyChanged. This allows me to bind the GUI to those classes and have the GUI react when those properties change. The problem is that for every single property that I want the class to have, I have to manually type in the code that fires the NotifyPropertyChanged event. While I can factor out the 3 lines of code for the event firing into a base class, I'm still left with this huge stream of property definitions. The properties all have the same shape (this should be a good clue that we can use codegen here) and all behave the same way. The getter returns the backing variable and the setter sets the backing variable and invokes a method which fires the property changed notification.

So in this T4 introduction I'm going to build a T4 template that automatically generates these notifier properties on a ViewModel class for me. It's going to be a partial class so if I want to add custom methods to the already generated members, I can do that without worry of having the generation process wipe out my code.

First thing to do is simply create a new file with the ".tt" extension in your project. In my case, I'm going to create a template called StateNotifierClass.tt. Just add a new file to the project with the ".tt" extension. Set the code for this template to the following:

<#@ template language="C#" #>
<#@ output extension="cs" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>

using System;
using System.ComponentModel;

namespace <#= this.Namespace #>
{
public partial class <#= this.ClassName #> : INotifyPropertyChanged
{
<# for (int idx = 0; idx < this.properties.GetLength(0); idx++)
   {
        #>
    private <#= this.properties[idx,0] #> _<#= this.properties[idx,1].ToLower() #>;
<#
}
#>

   public void DoHello()
   {
        Console.WriteLine("foo");
   }  

   <# for (int idx = 0; idx < this.properties.GetLength(0); idx++)
   {
        #>
    public <#= this.properties[idx,0] #> <#= this.properties[idx,1] #>
    {
        get
        {
            return _<#= this.properties[idx,1].ToLower() #>;
        }
        set
        {
            _<#= this.properties[idx,1].ToLower() #> = value;
            NotifyChange("<#= this.properties[idx,1]#>");
        }
    }

<#
   }
   #>  

   protected void NotifyChange(string propertyName)
   {
       if (PropertyChanged != null)
           PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
   }

   #region INotifyPropertyChanged Members

   public event PropertyChangedEventHandler PropertyChanged;

   #endregion
}
}

<#+
    string Namespace = "Demo";
    string ClassName = "DemoClass";

    string[,] properties = {
        {"int", "Property1"},
        {"string", "Property2"}};   
          
#>

With this template in place, you should see that your solution explorer has a new file beneath your template called StateNotifierClass.cs. Take a look at it, you'll see that it has a namespace, a classname, private member variables providing a backing store for the properties and public property definitions that are not only strongly typed without having to use generics but they also fire the property changed event notification.

This is great, but now what does it look like to build a real, live view model class using this template? Here is a view model class template for a stock quote that re-uses the previous template. As you can see, looking at this template is a LOT easier than looking at the huge pile of generated properties and you know immediately what simple, notification-enabled state members are exposed by that class:

<#
    this.Namespace = "DotNetAddict.Samples";
    this.ClassName = "StockQuote";
    this.properties = new string[,]{
        {"string", "Symbol"},
        {"decimal", "Price"},
        {"DateTime", "TimeStamp"},
        {"int", "Quantity"}};
#>
<#@ include file="StateNotifierClass.tt" #>

That's it! Obviously there is a lot more to T4 than what I'm showing here and if I end up spending more time using it I will do some more blog posts about it. The bottom line here is that for lightweight code generation tasks, you no longer need to look outside Visual Studio for third party codegen products... It's all right there for you. 

Obviously your mileage may vary, but I know from experience that having this tool available on some of my previous projects would've saved me DAYS of work and the end result would've been cleaner, more elegant, and a lot easier to change.

tags:        

links: digg this    del.icio.us    technorati    reddit

AddThis Social Bookmark Button




1. Kevin Hoffman left...
Thu 02 Apr 09 5:48 am

Just to add to this...another awesome side-effect of doing it this way is that you will never again fall victim to the typo problem where you spell the name of your property wrong in the setter and the notification never fires the way you want it to. Back in the good old days I remember a lot of people were skeptical of code generation. I say that, used tastefully and tactically, codegen is your friend.


2. Kuno left...
Fri 03 Apr 09 9:27 am

In fact, there is a solution of exactly the same problem using AOP: The PostSharp documentation (http://www.postsharp.org/) contains a code sample for using the CompoundAspect that does A) decorate a class with INotifyPropertyChanged, and B) decorate all publicly visible property setters with some notification code.