We’ve done a bunch of work on T4 in Visual Studio 2010 SP1 to enable template inheritance. 

A reasonable question at this point would be

“Why would you want inheritance in your text templates?”

Well, the typical reason would be the same as with any other code – because you want reuse and extensibility between a family of templates that have some significant similarities.  It’s really nice to be able to customize a template just by overriding a method as you would with any other O-O system.  Oleg Sych has an example of such a system on his excellent blog that works well with previous versions of T4 using nested classes, but I like to think the latest version of T4 makes it all a little bit easier.

I’m going to walk through a couple of examples of using inheritance with a themed sample, so let’s have a look at it.  I’ve previously discussed using simple C# data structures to drive a template.  This time I’ve got a couple of classes to provide metadata for simple data structures:

   1: public class TypeDescription
   2:   {
   3:       public string Name { get; set; }
   4:       public string Description { get; set; }
   5:       public List<TypePropertyDescription> Properties =
   6:                  new List<TypePropertyDescription>();
   7:   }
   8:  
   9:   public class TypePropertyDescription
  10:   {
  11:       public string Name { get; set; }
  12:       public string Type { get; set; }
  13:       public string Description { get; set; }
  14:   }

To keep things simple, a type is essentially jus a named and described bunch of properties. You can imagine using something like this to generate C# DAL classes, SQL schema creation scripts, ORM mappings and other typical application paraphernalia.

Here’s an example of populating the structure:

   1: this.Description = new TypeDescription
   2: {
   3:   Name="Book",  Description="A class to carry data about a book in a library system.",
   4:   Properties=
   5:   {
   6:     new TypePropertyDescription{Name="Title",         Type="string",    Description="The title of the book."},
   7:     new TypePropertyDescription{Name="AuthorID",      Type="string",    Description="The ID of the author of the book."},
   8:     new TypePropertyDescription{Name="ISBN",          Type="string",    Description="The standard ISBN number of the book."},
   9:     new TypePropertyDescription{Name="CopiesOwned",   Type="int",       Description="The number of copies the library owns."}
  10:   }
  11: };

Let’s say I’m going to generate a simple C# class from this metadata and I have a standard template that generates the following class:

   1: /// <summary>
   2: /// A class to carry data about a book in a library system.
   3: /// </summary>
   4: public class Book
   5: {
   6:     /// <summary>
   7:     /// The title of the book.
   8:     /// </summary>
   9:     public string Title { get; set; }
  10:  
  11:     /// <summary>
  12:     /// The ID of the author of the book.
  13:     /// </summary>
  14:     public string AuthorID { get; set; }
  15:  
  16:     /// <summary>
  17:     /// The standard ISBN number of the book.
  18:     /// </summary>
  19:     public string ISBN { get; set; }
  20:  
  21:     /// <summary>
  22:     /// The number of copies the library owns.
  23:     /// </summary>
  24:     public int CopiesOwned { get; set; }
  25:  
  26: }

Now on a new project, I decide that I need my data class to be serializable and that I want regular reminders not to edit the generated code (people don’t pay a lot of attention to the top of the file as it turns out).  I’d like the following:

   1: /// <summary>
   2: /// A class to carry data about a book in a library system.
   3: /// </summary>
   4: /// <remarks>
   5: /// This code generated by the DataClass.tt template - DO NOT MODIFY THIS CODE.
   6: /// </remarks>
   7: [Serializable]
   8: internal partial class Book
   9: {
  10:     /// <summary>
  11:     /// The title of the book.
  12:     /// </summary>
  13:     /// <remarks>
  14:     /// This code generated by the DataClass.tt template - DO NOT MODIFY THIS CODE.
  15:     /// </remarks>
  16:     public string Title { get; set; }
  17:  
  18:     /// <summary>
  19:     /// The ID of the author of the book.
  20:     /// </summary>
  21:     /// <remarks>
  22:     /// This code generated by the DataClass.tt template - DO NOT MODIFY THIS CODE.
  23:     /// </remarks>
  24:     public string AuthorID { get; set; }
  25:  
  26:     /// <summary>
  27:     /// The standard ISBN number of the book.
  28:     /// </summary>
  29:     /// <remarks>
  30:     /// This code generated by the DataClass.tt template - DO NOT MODIFY THIS CODE.
  31:     /// </remarks>
  32:     public string ISBN { get; set; }
  33:  
  34:     /// <summary>
  35:     /// The number of copies the library owns.
  36:     /// </summary>
  37:     /// <remarks>
  38:     /// This code generated by the DataClass.tt template - DO NOT MODIFY THIS CODE.
  39:     /// </remarks>
  40:     public int CopiesOwned { get; set; }
  41:  
  42: }

Next time, I’ll show you how to achieve this customization without substantially modifying the original template.

Technorati Tags: ,