Escaping Generics with T4 Templates
- by Gavin Stevens
I've been doing some work with T4 templates lately and ran into an issue which I couldn't find an answer to anywhere. I finally figured it out, so I thought I'd share the solution.
I was trying to generate a code class with a T4 template which used generics
The end result a method like:
public IEnumerator GetEnumerator()
{
return new TableEnumerator<Table>(_page);
}
the related section of the T4 template looks like this:
public IEnumerator GetEnumerator()
{
return new TableEnumerator<#=renderClass.Name#>(_page);
}
But this of course is missing the Generic Syntax for < > which T4 complains about because < > are reserved.
using syntax like <#<#><#=renderClass.Name#><#=<#> won't work becasue the TextTransformation engine chokes on them. resulting in : Error 2 The number of opening brackets ('<#') does not match the number of closing brackets ('#>')
even trying to escape the characters won't work: <#\<#><#=renderClass.Name#><#\<#> this results in:
Error 4 A Statement cannot appear after the first class feature in the template. Only boilerplate, expressions and other class features are allowed after the first class feature block.
The final solution delcares a few strings to represent the literals like this:
<#+
void RenderCollectionEnumerator(RenderCollection renderClass)
{
string open = "<";
string close =">";
#>
public partial class <#=renderClass.Name#> : IEnumerable
{
private readonly PageBase _page;
public <#=renderClass.Name#>(PageBase page)
{
_page = page;
}
public IEnumerator GetEnumerator()
{
return new TableEnumerator<#=open#><#=renderClass.Name#><#=close#>(_page);
}
}
<#+
}
#>
This works, and everyone is happy, resulting in an automatically generated class enumerator, complete with generics!
Hopefully this will save someone some time :)