Using T4 to Create an AppSettings Wrapper, Part 6
In this (almost) final post in the series on creating an AppSettings wrapper in T4 we’re going to package all the work we’ve done into an easily deployable and reusable package that we can extend to include other templates. We’ll also make sure that adding the template to a project is as easy as Add New Item.
Here’s the list of things we’ll accomplish
- Create a custom base class and move all the shared template functionality to it.
- Create a VS extension (VSIX) to install the parts of our template.
- Install the shared template components into a centralized directory so projects only need to include the core template.
There will be 4 projects by the time we’re done so now is a good time to create a new solution for all the template work. Create a new blank solution in Visual Studio (Other Project Types\Visual Studio Solutions). This solution will be able to host any number of T4 templates so you should use a generic name (i.e. MyTemplates).
We’ll be building a VSIX so the Visual Studio 2012 SDK needs to be installed. If the T4 Toolbox isn’t installed then that will be needed as well.
Shared Template Assembly
Let’s start by moving all the common functionality out of the nested template and into a reusable base class. The base class will contain any logic that can be shared across T4 templates. Create a new Class Library (i.e. TemplateLib) to store the base class and any additional functionality that will be needed by all templates. Since this will be hosted by VS it needs to target the .NET 4.5 framework. Delete any created class file.
We have been using a lot of assemblies so we need to add references to all of them. Note that when referencing VS assemblies there may be several. Prefer the versions in the Program Files directories over the VS directory to make it easier to move solutions.
- EnvDTE (version 22.214.171.124)
- T4 Toolbox installation directory
For the T4 Toolbox binaries you’ll unfortunately have to reference them from the installation directory where VS puts them. By default this will be a folder under your AppData\Local\Microsoft\VisualStudio\11.0\Extensions directory. If you like you could also copy the files into a shared assemblies folder under the solution to make it easier to use.
When adding EnvDTE and VSLangProj be sure to open the reference properties and set Embed Interop Types to False. Otherwise you’ll get several compilation warnings.
With all the references in place create a new class that will represent the base template class (i.e. MyTemplate). It should be public, abstract and derive from CSharpTemplate in the T4 Toolbox.
public abstract class MyTemplate : CSharpTemplate
Move all the members not specifically related to the app settings template into the base class. Make them protected so they are not exposed outside hierarchy. Here’s the members I see that should be moved.
- ActiveProject (and field)
- DteInstance (and field)
With the members moved the nested template can be cleaned up to remove unused namespaces and assembly references. All it contains now is the functionality specifically needed for dealing with the settings.
The nested template will need a reference to our assembly and an import for the namespace. Additional the nested template needs to derive from the new class.
<#@ assembly name="TemplateLib" #>
<#@ include file="T4Toolbox.tt" #>
<#@ Import namespace="TemplateLib" #>
public class AppSettingsTemplate : MyTemplate
At this point the template will not work correctly because T4 cannot find the custom assembly. To temporarily confirm all the changes work you can copy the assembly to the directory containing the templates.
Item Template Project
In order to use the template developers will need to be able to add the template from Add New Item. To simplify deployment we can create a new template project that installs the items into the appropriate location. This project can install any number of item templates so as more T4 templates are created they can be added here.
Create a new Item Template project (Visual C#\Extensibility\C# Item Template) called ItemTemplates. Since we might have several different templates in this project I like to create a folder for each template (i.e. AppSettings). Each new T4 template can be placed into its own subfolder so there is no worries about collisions. Every time a new item template is added the following steps need to be followed.
- Create a subfolder in the project
- Add the .tt file to the subfolder along with the .vstemplate and optional .ico files
- For each .tt file set the following properties for the item
- Build Action = Content
- Custom Tool = (blank)
- Include in VSIX = True
- For the .vstemplate file set the following properties
- Build Action = VSTemplate
- Include in VSIX = False
- Category = (see below)
- In the VSTemplate file
- Set RequiredFrameworkVersion as appropriate
- Set a unique TemplateID
- Set the name and description
- Set DefaultName accordingly
- Reference the icon included in the project
- Add any referenced assemblies
- Change the existing ProjectItem entry to reference the .tt file instead
- For each ProjectItem set the ItemType to the appropriate Build Action (for .tt files it should be set to None)
Move the .vstemplate and .ico files that were generated into the template folder. The .cs file can be deleted. Rename the copied files to match the template name. Finally copy the root T4 template from previous articles into the folder. Then follow the steps above to complete the process.
The Category property for the .vstemplate allows you to group your templates into a folder in Add New Items. It should be used to keep your custom templates separate from VS or others.
This post is getting long so it’s time to take a break. In the next (and final) post we’ll create the other 2 projects to finish up the deployment of the T4 template.