T4 Template Design: Nested Template Class


Nested Template Class is one of T4 template design techniques that can be used to develop reusable templates. It defines the main template as a nested TextTransformation class in a class feature block. The nested class uses properties to define template parameters and virtual methods to define extension points. The calling template uses an include directive to merge code of the main template into the calling template. Main template can be extended by subclassing the nested template class and overriding its virtual methods. The nested template class is instantiated in the statement block of the calling template.

Main Template

<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#+
    class ClassTemplate: TextTransformation
    {
        private string _className;

        public string ClassName
        {
            get { return _className; }
            set { _className = value; }
        }

        protected virtual void WritePropertyAttributes()
        {
        }

        public override string TransformText()
        {
#>
public class <#= ClassName #>
{
    <#+ WritePropertyAttributes(); #>
    public string Property
    {
        get { return _property; }
        set { _property = value; }
    }
}
<#+
            return GenerationEnvironment.ToString();
        }
    }
#>

Calling Template

<#@ template language="C#" #>
<#@ include file="Template.tt" #>
<#
    DataContractTemplate template = new DataContractTemplate();
    template.ClassName = "TestClass";
    string output = template.TransformText();
    Write(output);
#>
<#+
    class DataContractTemplate: ClassTemplate
    {
        protected override void WritePropertyAttributes()
        {
#>
[DataMember]
<#+
        }
    }
#>

Output

public class TestClass
{
    [DataMember]
    public string Property
    {
        get { return _property; }
        set { _property = value; }
    }
}

How It Works

Nested Template Class technique uses a class feature block of the main template file to define a nested class which descends from TextTransformation. In the example above, this class is called ClassTemplate. This nested class class overrides the abstract TransformText method and takes advantage of T4 compiling all text blocks into calls to this.Write(…) method no matter where they are located. Specifically, text blocks inside of the nested template class are compiled into calls to the Write method of the nested class.

Main template defines template parameters as public properties of the nested class. Template extension points are defined as virtual methods. In the example above, ClassName property is a template parameter and WritePropertyAttributes method is an extension point.

Calling template customizes the main template by creating a descendant of the nested class which overrides the virtual methods defined by its parent. In the example above, DataContractTemplate extends the ClassTemplate by overriding the virtual WritePropertyAttributes method.

Calling template invokes the main template in its statement block by instantiating the nested template class and calling its TransformText method.

Here is what the calling template looks like when compiled by T4.

using System;
using Microsoft.VisualStudio.TextTemplating;
using Microsoft.VisualStudio.TextTemplating.VSHost;

namespace Microsoft.VisualStudio.TextTemplatingE73F111EA693676
{
  public class GeneratedTextTransformation: TextTransformation
  {
    public override string TransformText()
    {
      DataContractTemplate template = new DataContractTemplate();
      template.ClassName = "TestClass";
      string output = template.TransformText();
      Write(output);
      return this.GenerationEnvironment.ToString();
    }

    class DataContractTemplate : ClassTemplate
    {
      protected override void WritePropertyAttributes()
      {
        this.Write("[DataMember]\r\n");
      }
    }

    class ClassTemplate : TextTransformation
    {
      private string _className;

      public string ClassName
      {
        get { return _className; }
        set { _className = value; }
      }

      protected virtual void WritePropertyAttributes()
      {
      }

      public override string TransformText()
      {
        this.Write("public class ");
        this.Write(ToStringHelper.ToStringWithCulture(ClassName));
        this.Write("\r\n{\r\n\t");
        WritePropertyAttributes();
        this.Write("\tpublic string Property\r\n\t{\r\n\t\t" +
            "get { return _property; }\r\n\t\t" +
            "set { _property = value; }\r\n\t}\r\n}\r\n");
        return GenerationEnvironment.ToString();
      }
    }
  }
}

Pros

This technique allows to explicitly define strongly-typed template parameters as properties of the nested template class.

This technique allows to completely encapsulate main template inside the nested template class. Template developer controls access to the implementation using standard .NET visibility attributes (private, protected, public).

This technique allows to explicitly define extension points as virtual methods of the nested template class. Main template can provide default implementation for extension methods that don’t require calling template to implement them. New extension methods can be added without breaking existing calling

This technique allows to compose multiple templates to generate multiple outputs from a single calling template.

Cons

This technique is more complex than Included Template Method and requires understanding of how T4 generates implementation of the TransformText method in order to hand-code it correctly.

Conclusion

Nested Template Class technique allows developer to take full advantage of standard C# and Visual Basic language features, such as properties to define template parameters, private visibility for encapsulation, inheritance and virtual methods for extensibility. This technique allows developing templates for the most complex scenarios of cross-project and cross-team reuse.

About T4

T4 (Text Template Transformation Toolkit) is a template-based code generation engine. It is available in Visual Studio 2008 and as a download in DSL and GAT toolkits for Visual Studio 2005. T4 engine allows you to use ASP.NET-like template syntax to generate C#, T-SQL, XML or any other text files.

For more information about T4, check out my previous article.

Information and Links

Join the fray by commenting, tracking what others have to say, or linking to it from your blog.


Other Posts
T4 Template for Generating ADO.NET Entity Framework Stored Procedures
T4 Template Design: Standalone Template

Write a Comment

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

Reader Comments

Be the first to leave a comment!