Cyotek Development Bloghttps://devblog.cyotek.com/tag/template/atom.xml2016-03-20T07:09:05ZGenerating code using T4 templatesurn:uuid:b29d688c-04be-4626-a622-154dab1c7cbe2016-03-20T07:09:05Z2016-03-20T07:09:05Z<p>Recently I was updating a library that contains two keyed
collection classes. These collections aren't the usual
run-of-the-mill collections as they need to be able to support
duplicate keys. Normally I'd inherit from <code>KeyedCollection</code> but
as with most collection implementations, duplicate keys are not
permitted in this class.</p>
<p>I'd initially solved the problem by simply creating my own base
class to fit my requirements, and this works absolutely fine.
However, this wasn't going to suffice as a long term solution as
I don't want that base class to be part of a public API,
especially a public API that has nothing to do with offering
custom base collections to consumers.</p>
<p>Another way I could have solved the problem would be to just
duplicate all that boilerplate code, but that was pretty much a
last resort. If there's one thing I really don't like doing it's
fixing the same bugs over and over again in duplicated code!</p>
<p>Then I remembered about <a href="https://msdn.microsoft.com/en-us/library/bb126445.aspx" rel="external nofollow noopener">T4 Templates</a>, which has been a
feature of Visual Studio for some time I believe. Previously my
only interaction with them has been via <a href="http://www.toptensoftware.com/petapoco/" rel="external nofollow noopener">PetaPoco</a>, a rather
marvellous library which generates C# classes based on a
database model, provides a micro ORM, and has powered cyotek.com
for years. This proved to be a nice solution for my collection
issue, and I thought I'd document the process here, firstly as
it's been a while since I blogged, and secondly as a reference
for &quot;next time&quot;.</p>
<h2 id="creating-the-template">Creating the template</h2>
<p>First, we need to create a template. To do this from Visual
Studio, open the <strong>Project</strong> menu and click <strong>Add New Item</strong>.
The select <em>Text Template</em> from the list of templates, give it a
name, and click <strong>Add</strong>.</p>
<p>This will create a simple file containing something similar to
the following</p>
<figure class="lang-csharp highlight"><figcaption><span>csharp</span></figcaption><pre class="code">
<span class="symbol">&lt;</span>#<span class="symbol">@</span> template debug<span class="symbol">=</span><span class="string">&quot;false&quot;</span> hostspecific<span class="symbol">=</span><span class="string">&quot;false&quot;</span> language<span class="symbol">=</span><span class="string">&quot;C#&quot;</span> #<span class="symbol">&gt;</span>
<span class="symbol">&lt;</span>#<span class="symbol">@</span> assembly name<span class="symbol">=</span><span class="string">&quot;System.Core&quot;</span> #<span class="symbol">&gt;</span>
<span class="symbol">&lt;</span>#<span class="symbol">@</span> import <span class="keyword">namespace</span><span class="symbol">=</span><span class="string">&quot;System.Linq&quot;</span> #<span class="symbol">&gt;</span>
<span class="symbol">&lt;</span>#<span class="symbol">@</span> import <span class="keyword">namespace</span><span class="symbol">=</span><span class="string">&quot;System.Text&quot;</span> #<span class="symbol">&gt;</span>
<span class="symbol">&lt;</span>#<span class="symbol">@</span> import <span class="keyword">namespace</span><span class="symbol">=</span><span class="string">&quot;System.Collections.Generic&quot;</span> #<span class="symbol">&gt;</span>
<span class="symbol">&lt;</span>#<span class="symbol">@</span> output extension<span class="symbol">=</span><span class="string">&quot;.txt&quot;</span> #<span class="symbol">&gt;</span>
</pre>
</figure>
<p>A T4 template is basically the content you want to output, with
one or more control blocks for dynamically changing the content.
In other words, it's just like a Razor HTML file, WebForms,
Classic ASP, PHP... the list is probably endless.</p>
<p>Each block is delimited by <code>&lt;#</code> and <code>#&gt;</code>, the <code>@</code> symbols above
are directives. We can use the <code>=</code> symbol to inject content. For
example, if modify the template to include the following lines</p>
<figure class="lang-html highlight"><figcaption><span>html</span></figcaption><pre class="code">
<span class="literal">&lt;</span><span class="name">html</span><span class="literal">&gt;</span>
<span class="literal">&lt;</span><span class="name">head</span><span class="literal">&gt;</span>
<span class="literal">&lt;</span><span class="name">title</span><span class="literal">&gt;</span>&lt;#=DateTime.Now#&gt;<span class="literal">&lt;/</span><span class="name">title</span><span class="literal">&gt;</span>
<span class="literal">&lt;/</span><span class="name">head</span><span class="literal">&gt;</span>
<span class="literal">&lt;/</span><span class="name">html</span><span class="literal">&gt;</span>
</pre>
</figure>
<p>Save the file, then in the Project Explorer, expand the node for
the file - by default the auto generated content will be nested
beneath your template file, as with any other designer code.
Open the generated file and you should see something like this</p>
<figure class="lang-html highlight"><figcaption><span>html</span></figcaption><pre class="code">
<span class="literal">&lt;</span><span class="name">html</span><span class="literal">&gt;</span>
<span class="literal">&lt;</span><span class="name">head</span><span class="literal">&gt;</span>
<span class="literal">&lt;</span><span class="name">title</span><span class="literal">&gt;</span>03/12/2016 12:41:07<span class="literal">&lt;/</span><span class="name">title</span><span class="literal">&gt;</span>
<span class="literal">&lt;/</span><span class="name">head</span><span class="literal">&gt;</span>
<span class="literal">&lt;/</span><span class="name">html</span><span class="literal">&gt;</span>
</pre>
</figure>
<h2 id="changing-the-file-name">Changing the file name</h2>
<p>The name of the auto-generated file is based on the underlying
template, so make sure your template is named appropriately. You
can get the desired file extension by including the following
directive in the template</p>
<figure class="lang-csharp highlight"><figcaption><span>csharp</span></figcaption><pre class="code">
<span class="symbol">&lt;</span>#<span class="symbol">@</span> output extension<span class="symbol">=</span><span class="string">&quot;.txt&quot;</span> #<span class="symbol">&gt;</span>
</pre>
</figure>
<p>If no directive at all is present, then <code>.cs</code> will be used.</p>
<h2 id="including-other-files">Including other files</h2>
<p>So far, things are looking positive - we can create a template
that will spit out our content, and dynamically manipulate it.
But it's still one file, and in my use case I'll need at least
two. Enter - the include directive. By including this directive,
the contents of another file will be injected, allowing us to
have multiple templates generated from one common file.</p>
<figure class="lang-csharp highlight"><figcaption><span>csharp</span></figcaption><pre class="code">
<span class="symbol">&lt;</span>#<span class="symbol">@</span> include file<span class="symbol">=</span><span class="string">&quot;CollectionBase.ttinclude&quot;</span> #<span class="symbol">&gt;</span>
</pre>
</figure>
<p>If your include file makes use of variables, they are
automatically inherited from the parent template, which is the
key piece of magic I need.</p>
<h2 id="adding-conditional-logic">Adding conditional logic</h2>
<p>So far I've mentioned the <code>&lt;%@ ... %&gt;</code> directives, and the <code>&lt;%= ... %&gt;</code> insertion blocks. But what about if you want to include
code for decision making, branching, and so on? For this, you
use the <code>&lt;% ... %&gt;</code> syntax without any symbols on the opening
delimiter. For example, I use the following code to include a
certain <code>using</code> statement if a variable has been set</p>
<figure class="lang-csharp highlight"><figcaption><span>csharp</span></figcaption><pre class="code">
<span class="keyword">using</span> System<span class="symbol">.</span>Collections<span class="symbol">.</span>Generic<span class="symbol">;</span>
<span class="symbol">&lt;</span># <span class="keyword">if</span> <span class="symbol">(</span>UsePropertyChanged<span class="symbol">)</span> <span class="symbol">{</span> #<span class="symbol">&gt;</span>
<span class="keyword">using</span> System<span class="symbol">.</span>ComponentModel<span class="symbol">;</span>
<span class="symbol">&lt;</span># <span class="symbol">}</span> #<span class="symbol">&gt;</span>
</pre>
</figure>
<p>In the above example, the line using
<em>System.Collections.Generic;</em> will always be written. On the
other hand, the <em>using System.ComponentModel;</em> line will only be
written if the <code>UsePropertyChanged</code> variable has been set.</p>
<blockquote>
<p>Note: Remember that T4 templates are compiled and executed. So
syntax errors in your C# code (such as forgetting to assign
(or define) the <code>UsePropertyChanged</code> variable above) will
cause the template generation to fail, and any related output
files to be only partially generated, if at all.</p>
</blockquote>
<h2 id="debugging-templates">Debugging templates</h2>
<p>I haven't really tested this much, as my own templates were
fairly straight forward and didn't have any complicated logic.
However, you can stick breakpoints in your <code>.tt</code> or <code>.ttinclude</code>
files, and then debug the template generation by context
clicking the template file and choosing <strong>Debug T4 Template</strong>
from the menu. For example, this may be useful if you create
helper methods in your templates for performing calculations.</p>
<h2 id="putting-it-all-together">Putting it all together</h2>
<p>The two collections I want to end up with are
<code>ColorEntryCollection</code> and <code>ColorEntryContainerCollection</code>. Both
will share a lot of boilerplate code, but also some custom code,
so I'll need to include dedicated CS files in addition to the
auto-generated ones.</p>
<p>To start with, I create my <code>ColorEntryCollection.cs</code> and
<code>ColorEntryContainerCollection.cs</code> files with the following
class definitions. Note the use of the <code>partial</code> keyword so I
can have the classes built from multiple code files.</p>
<figure class="lang-csharp highlight"><figcaption><span>csharp</span></figcaption><pre class="code">
<span class="keyword">public</span> <span class="keyword">partial</span> <span class="keyword">class</span> ColorEntryCollection
<span class="symbol">{</span>
<span class="symbol">}</span>

<span class="keyword">public</span> <span class="keyword">partial</span> <span class="keyword">class</span> ColorEntryContainerCollection
<span class="symbol">{</span>
<span class="symbol">}</span>
</pre>
</figure>
<p>Next, I created two T4 template files,
<code>ColorEntryCollectionBase.tt</code> and
<code>ColorEntryContainerCollectionBase.tt</code>. I made sure these had
different file names to avoid the auto-generated <code>.cs</code> files
from overwriting the custom ones (I didn't test to see if VS
handles this, better safe than sorry).</p>
<p>The contents of the <code>ColorEntryCollectionBase.tt</code> file looks
like this</p>
<figure class="lang-csharp highlight"><figcaption><span>csharp</span></figcaption><pre class="code">
<span class="symbol">&lt;</span>#
<span class="keyword">string</span> ClassName <span class="symbol">=</span> <span class="string">&quot;ColorEntryCollection&quot;</span><span class="symbol">;</span>
<span class="keyword">string</span> CollectionItemType <span class="symbol">=</span> <span class="string">&quot;ColorEntry&quot;</span><span class="symbol">;</span>
<span class="keyword">bool</span> UsePropertyChanged <span class="symbol">=</span> <span class="keyword">true</span><span class="symbol">;</span>
#<span class="symbol">&gt;</span>

<span class="symbol">&lt;</span>#<span class="symbol">@</span> include file<span class="symbol">=</span><span class="string">&quot;CollectionBase.ttinclude&quot;</span> #<span class="symbol">&gt;</span>
</pre>
</figure>
<p>The contents of <code>ColorEntryContainerCollectionBase.tt</code> are</p>
<figure class="lang-csharp highlight"><figcaption><span>csharp</span></figcaption><pre class="code">
<span class="symbol">&lt;</span>#
<span class="keyword">string</span> ClassName <span class="symbol">=</span> <span class="string">&quot;ColorEntryContainerCollection&quot;</span><span class="symbol">;</span>
<span class="keyword">string</span> CollectionItemType <span class="symbol">=</span> <span class="string">&quot;ColorEntryContainer&quot;</span><span class="symbol">;</span>
<span class="keyword">bool</span> UsePropertyChanged <span class="symbol">=</span> <span class="keyword">false</span><span class="symbol">;</span>
#<span class="symbol">&gt;</span>

<span class="symbol">&lt;</span>#<span class="symbol">@</span> include file<span class="symbol">=</span><span class="string">&quot;CollectionBase.ttinclude&quot;</span> #<span class="symbol">&gt;</span>
</pre>
</figure>
<p>As you can see, the templates are very simple - basically just
setting it up the key information that is required to generate
the template, then including another file - and it is this file
that has the true content.</p>
<p>The final piece of the puzzle therefore, was to create my
<code>CollectionBase.ttinclude</code> file. I copied into this my original
base class, then pretty much did a search and replace to replace
hard coded class names to use T4 text blocks. The file is too
big to include in-line in this article, so I've just included
the first few lines to show how the different blocks fit
together.</p>
<figure class="lang-csharp highlight"><figcaption><span>csharp</span></figcaption><pre class="code">
<span class="keyword">using</span> System<span class="symbol">;</span>
<span class="keyword">using</span> System<span class="symbol">.</span>Collections<span class="symbol">;</span>
<span class="keyword">using</span> System<span class="symbol">.</span>Collections<span class="symbol">.</span>Generic<span class="symbol">;</span>
<span class="symbol">&lt;</span># <span class="keyword">if</span> <span class="symbol">(</span>UsePropertyChanged<span class="symbol">)</span> <span class="symbol">{</span> #<span class="symbol">&gt;</span>
<span class="keyword">using</span> System<span class="symbol">.</span>ComponentModel<span class="symbol">;</span>
<span class="symbol">&lt;</span># <span class="symbol">}</span> #<span class="symbol">&gt;</span>

<span class="keyword">namespace</span> Cyotek<span class="symbol">.</span>Drawing
<span class="symbol">{</span>
 <span class="keyword">partial</span> <span class="keyword">class</span> <span class="symbol">&lt;</span>#<span class="symbol">=</span>ClassName#<span class="symbol">&gt;</span> <span class="symbol">:</span> IList<span class="symbol">&lt;&lt;</span>#<span class="symbol">=</span>CollectionItemType#<span class="symbol">&gt;&gt;</span>
 <span class="symbol">{</span>
 <span class="keyword">private</span> <span class="keyword">readonly</span> IList<span class="symbol">&lt;&lt;</span>#<span class="symbol">=</span>CollectionItemType#<span class="symbol">&gt;&gt;</span> _items<span class="symbol">;</span>
 <span class="keyword">private</span> <span class="keyword">readonly</span> IDictionary<span class="symbol">&lt;</span><span class="keyword">string</span><span class="symbol">,</span> SmallList<span class="symbol">&lt;&lt;</span>#<span class="symbol">=</span>CollectionItemType#<span class="symbol">&gt;&gt;&gt;</span> _nameLookup<span class="symbol">;</span>

 <span class="keyword">public</span> <span class="symbol">&lt;</span>#<span class="symbol">=</span>ClassName#<span class="symbol">&gt;</span><span class="symbol">(</span><span class="symbol">)</span>
 <span class="symbol">{</span>
 _items <span class="symbol">=</span> <span class="keyword">new</span> List<span class="symbol">&lt;&lt;</span>#<span class="symbol">=</span>CollectionItemType#<span class="symbol">&gt;&gt;</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">;</span>
 _nameLookup <span class="symbol">=</span> <span class="keyword">new</span> Dictionary<span class="symbol">&lt;</span><span class="keyword">string</span><span class="symbol">,</span> SmallList<span class="symbol">&lt;&lt;</span>#<span class="symbol">=</span>CollectionItemType#<span class="symbol">&gt;&gt;&gt;</span><span class="symbol">(</span>StringComparer<span class="symbol">.</span>OrdinalIgnoreCase<span class="symbol">)</span><span class="symbol">;</span>
 <span class="symbol">}</span>
</pre>
</figure>
<p>All the <code>&lt;#=ClassName#&gt;</code> blocks get replaced with the
<code>ClassName</code> value from the parent <code>.tt</code> file, as do the
<code>&lt;#=CollectionItemType#&gt;</code> blocks. You can also see the
<code>UsePropertyChanged</code> variable logic I described earlier for
inserting a <code>using</code> statement - I used the same functionality in
other places to include entire methods or just extra lines where
appropriate.</p>
<p>Then it was just a case of right clicking the two <code>.tt</code> files I
created earlier and selecting <strong>Run Custom Tool</strong> from the
content menu which caused the contents of my two collections to
be fully generated from the template. The only thing left to do
was to then add the custom implementation code to the two main
class definitions and job done.</p>
<p>I also used the same process to create a bunch of standard tests
for those collections rather than having to duplicate those too.</p>
<h2 id="thats-all-folks">That's all folks</h2>
<p>Although normally you probably won't need this sort of
functionality, the fact that it is built right into Visual
Studio and so easy to use is pretty nice. It has certainly
solved my collection issue and I'll probably use it again in the
future.</p>
<p>While writing this article, I had a quick look around the <a href="https://msdn.microsoft.com/en-us/library/bb126445.aspx" rel="external nofollow noopener">MSDN
documentation</a> and there's plenty of advanced functionality
you can use with template generation which I haven't covered, as
just the basics were sufficient for me.</p>
<p>Although I haven't included the usual sample download with this
article, I think it's straightforward enough that it doesn't
need one. The final code will be available on our <a href="https://github.com/cyotek" rel="external nofollow noopener">GitHub</a>
page at some point in the future, once I've finished adding more
tests, and refactored a whole bunch of extremely awkwardly named
classes.</p>
<h2 id="update-history">Update History</h2>
<ul>
<li>2016-03-20 - First published</li>
<li>2020-11-21 - Updated formatting</li>
</ul>

<p><small>
All content <a href="https://devblog.cyotek.com/copyright-and-trademarks">Copyright (c) by Cyotek Ltd</a> or its respective writers. Permission to reproduce news and web log entries and other RSS feed content in unmodified form without notice is granted provided they are not used to endorse or promote any products or opinions (other than what was expressed by the author) and without taking them out of context. Written permission from the copyright owner must be obtained for everything else.<br />Original URL of this content is https://devblog.cyotek.com/post/generating-code-using-t4-templates .
</small></p>Richard Mosshttps://www.cyotek.com/richard.moss@cyotek.com