T4 Code Generation with TDS 4.0 Beta for Sitecore

Note: Content for this blog post is based on TDS 4.0 Beta and does not necessarily reflect the features of the public release

Most developers and development teams working with Sitecore will now be using some form of object mapping when working Sitecore Items programatically. This has many benefits including

  1. Working with strongly typed field values
  2. Performing CRUD operations through centralized code
  3. Abstracting Sitecore away from your domain model

Template classes typically inherit from Sitecore’s CustomItem class. From this point on you have access to the underlying Item as you would normally do but you now have the option to build wrapper code to perform operations such as returning a strongly typed fields

public class HomeItem : CustomItem
{
    public HomeItem(Item innerItem) : base(innerItem) { }

    public int NewsItemLimit
    {
        get { return Convert.ToInt32(this["News Item Limit"]); }
    }
}

HomeItem home = new HomeItem(Sitecore.Context.Item);

int newsLimit = home.NewsItemLimit;

Hand writing classes per template each containing a getter per field is a tedious and error prone approach to object mapping that can be replaced by either

  1. Writing c# code using the Sitecore API to generate classes on demand or on the item:created event
  2. Using the CustomItemGenerator by Velir for integration with the Sitecore UI
  3. Using Glass.Mapper by Mike Edwards

With the new Beta release of Team Development for Sitecore we can now leverage T4 templates (available as part of Visual Studio since Visual Studio 2005) to automatically generate classes for either of the solutions mentioned above every time we sync Sitecore with our TDS projects. Better still if using Sitecore Rocks the TDS sync happens automatically on save instead of having to use the sync window.

TDS allows us to specify a header template, a T4 template that runs only once and generates code at the top of the target file and a base template, a T4 template that executes for every item in the TDS project. All of the resulting code is merged into a single file. You can choose the name of the file and the target project you want it to appear in using the code generation tab in your TDS project properties.

TDS Code Generation Configuration

Your header template will typically be used to include using statements required by the generated code. If you don’t want templates to be executed for every item in your TDS project you can also select a template to run for a particular item and it’s descendants by using the item properties window.

T4 templates can be added to your TDS project once you have checked the enable code generation checkbox in the project properties. Once you save the project a “Code Generation Templates” item will appear

TDS Project

Selecting add new item will bring up a dialogue asking you to choose a template type. T4 templates are made up of

  1. Text Blocks
  2. Expression Blocks
  3. Control Blocks
  4. Feature blocks – control blocks cannot appear below feature blocks
Text Block

<#
	// control block
	for (int i = 0; i < length; i++)
	{
		WriteLine(i);
	}
#>

<#= WriteLine("Expression Block") #>

<#+
	public class FeatureBlock
	{
	}
#>

For each T4 item template TDS passes in a Model object of type SitecoreItem. The Model gives us access to properties of the current item for example

  1. Name
  2. Path
  3. Fields – Standard Sitecore fields that are configured in the Code Generation tab of the TDS project properties
  4. Id

SitecoreItem can be cast as SitecoreTemplate or SitecoreField which both inherit from SitecoreItem.

Once we have access to the SitecoreTemplate which also exposes base templates we have what we need to construct a simple T4 template, the following template will result in a class per template that resembles the example class above

<#@ template language="C#" debug="true" #>
<#@ import namespace="HedgehogDevelopment.SitecoreProject.VSIP.CodeGeneration.Models" #>
<#@ parameter name="Model" type="HedgehogDevelopment.SitecoreProject.VSIP.CodeGeneration.Models.SitecoreItem" #>

<#
if (Model is SitecoreTemplate)
{
var template = Model as SitecoreTemplate;
#>
namespace <#= Model.Namespace #>
{
public partial class <#= TitleCase(Model.Name) #> : CustomItem
{
public <#= className #>(Item innerItem) : base(innerItem) { }

<# foreach (var field in template.Fields) { #>
public <#= ReturnType(field.Type) #> <#= TitleCase(field.Name) #>
{
get { return this["<#= field.Name #>"]; }
}
<#}#>
	}
}
<#}#>

<#+

public string ReturnType(string typeName)
{
	if (typeName == "integer" || typeName == "number")
	{
		return "int?";
	}

return "string";
}

public string TitleCase(string name)
{
name = Regex.Replace(name, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$1 ");
name = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(name);
name = Regex.Replace(name, @"[^a-zA-Z0-9]", String.Empty);
name = Regex.Replace(name, @"(^[0-9])", "Z$1");

return name;
}
#>

Once you have a grasp of the T4 syntax and features we have a very powerful templating engine that allows us to instantly map Sitecore objects using a variety of techniques.

Happy coding!

Advertisements