C# Express and item template customization

There was an interesting post a while back in the Visual C# IDE forum asking whether or not it was possible to automatically insert company specific information every time that a new file is added to a C# project (specifically in C# Express 2005). It turns out that it is possible. The idea is to create a new item template that contains this information by default. Item templates are the name of the elements that appear in the "Add New Item..." dialog. This dialog appears when a project is right-clicked and Add New Item... is selected. 

In order to illustrate this, let's take a look at two possibilities for creating a template which adds a new class. Item templates are stored in zip files. The set that are installed by default for C# Express are located at Program Files\Microsoft Visual Studio 8\Common7\IDE\VCSExpress\ItemTemplates\1033. Copy the Class.zip file, which represents the class item template, to My Documents\Visual Studio 2005\Templates\Item Templates\Visual C#\. The .zip file contains two files, a .vstemplate file and a .cs file. The .vstemplate file controls a number of the display attributes that are shown in the Add New Item dialog, such as the name of the template, the icon, the description, etc. It also contains all of the information that the project system uses to figure out which files this item template adds to the project. It is a fairly straightforward XML format. In this case, let's modify the name slightly so it's clear that the template has been added. That requires changing the line in the .vstemplate file from:

<Name Package="{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}" ID="2245" />

to:

<Name>Custom Class Template</Name>

The only other change that needs to be made is in .cs file. Near the end of the .vstemplate file there is a line that indicates the file, Class.cs, in which to 'replace parameters'. ‘Replace parameters’ indicates that the project system should do a textual replacement in the named file looking for certain strings. The project system provides some default replacement strings which are documented here. In this specific case these parameters may be enough, we simply need to modify the Class.cs file and add the company comment at the top of the file in the following format:

/*--------------------------------------------------------
* $itemname$.cs - file description
*
* Version: 1.0
* Author: Anson Horton
* Created: $time$
*
* Revisions:
* -------------------------------------------------------*/

Zip those two files back up, and verify it's in the directory mentioned above. Start up C# Express, create a project, and right-click on it to add a new item. Notice that in the lower portion of the Add New Item dialog, there is a section called "My Templates." A template called Custom Class should appear there; when that template is added to the project it will create a class with the header above (of course, you'll want to change the author name :). 

The only unfortunate aspect of this approach is that it’s not possible to format the time outside of the format that is provided by default and it’s not really possible to share the template with coworkers because the user name is hard-coded into the item template. There is a slightly more complicated alternative which is simply an extension of the approach above. The project system provides a mechanism for creating 'Wizard' templates. These can be arbitrarily complicated, but in this case it would be fairly trivial. The idea is to create a class which implements the IWizard interface (defined in Microsoft.VisualStudio.TemplateWizardInterface). The majority of the methods would simply be left blank (they shouldn’t throw an exception). The only two that would need to be implemented would be RunStarted and ShouldAddProjectItem. This would look something like:

public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
{
replacementsDictionary.Add("$UserName$", Environment.UserName);
replacementsDictionary.Add("$DateTime$", DateTime.Now.ToString());
}

public bool ShouldAddProjectItem(string filePath)
{
    return true;
}

This assembly is then built, signed, and installed into the GAC. The RunStarted method is simply modifying the set of template parameters that can be used in the source file (the project system uses these as lookups when it does its textual ‘replace parameters’). In this case it is possible to have the user name of the user who started C# Express as well as modifying the format of the date time. In order to tell the project system to use this wizard, the .vstemplate file is modified with a line similar to:

<WizardExtension>
<Assembly>CustomItemTemplateWizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=29ab57250b4cf6c3</Assembly>
<FullClassName>CustomItemTemplateWizard.ExampleWizard</FullClassName>
</WizardExtension>

This line appears below the TemplateContent section. After that, it's simply a matter of updating the Class.cs file to use the additional template parameters:

* Author: $UserName$
* Created: $DateTime$

There is more information about creating wizard templates here.