Templates Galore: Live Templates

A couple of months ago I was doing a talk at DevSum, Stockholm. It was a room full of developers, 90% of whom had heard of ReSharper and 80% of them used it. What surprised me however was that only a couple of folks knew about Live Templates, which left me wondering how many outside of the that group actually knew about them too. Thus, in an attempt to expand the reach, we’ll take a look at what Live Templates and in future posts look at Surround and File Templates

Snippets on Speed

Live Templates enhances the Visual Studio Code Snippets by providing more functionality and easier management. To open up the Live Templates manager, we click on the ReSharper menu and select Live Templates:

ReSharper has four groups of templates:

Predefined: Predefined by ReSharper

User Templates: Templates defined by the user

Personal Solution Templates: Templates that are specific to a solution

Shared Solution Templates: Templates that are specific to a solution and can be shared with others

Each group consists of various categories based on the type of project/files we are working on. Many of these also import the default Snippets that are available in Visual Studio. From this screen there are various operations we can perform such as adding, removing, editing templates, as well as importing and them. Editing and Creating Templates is where some of the juice is, so let’s see how we can create a new template.

Creating Templates

Templates consists of literal strings and variables. The idea is to combine these to maximize efficiency when typing. They can be used for a variety of things, from creating classes, DTO’s or skeletons for unit tests, among others. Let’s say we like to create entities that usually have an Id field prefixed (this is not personal!) with the name of the class, along with some other properties. The type of my Id is not necessarily known beforehand. It can be of type string, GUID, etc. Here’s a sample:

3. This opens up the editor where we can type our text (literal strings and variables).

4. We need to provide a shortcut for our template, which will be used to invoke it (we’ll see how later). Type “be” in the Shortcut field. In the Description type “Business Entity”

5. Type the following in the text area (black in the figure above)

The different colors have meanings (these Colors can be configured under Tools | Options | Fonts and Color. Look for “ReSharper Live xxxxx” entries). There are 3 types of elements in the text:

text literal

template keyword

variables

The text literal is everything that is in white text, such as “public class” and “{ get; private set;}”. Anything literal will appear as is when we invoke the template. The second type of element is the $END$ keyword. This is used to tell ReSharper where we want the cursor to be positioned once we have finished invoking and interacting with the template. Finally we have the variables. These are elements that can be used to interact with the template. A variable is designated using the $ prefix and suffix. That is, anytime we type a word prefixed and suffixed with a $ sign, ReSharper will automatically convert it to a variable. The effect that this has is that when we invoke the template, we can iterate through the different variables to type a value. In our case, since we want to establish the classname during its invocation, we make the $className$ a variable. The same occurs with $idType$, since we don’t know what type we want the Id to be (this is for demonstration purposes, normally most entities have the same type for their Id). Finally comes the Id property. We said we want this to resemble the classname suffixed with Id. As such we just suffix it with the word Id.

6. Close the Editor.

7. Open up an existing file and locate an empty are where we can create a new class. Now type “b” and we should get Intellisense for all templates that start with “b”. Locate “be” and hit TAB (or ENTER)

ending up with:

ReSharper has generated the core code of the template and is now ready for our input. The cursor is currently positioned at className, where can type in the class name. Notice that as we type, the value of the property name is automatically updated, as expected. Once we finish typing className we hit TAB (or ENTER) and ReSharper positions us at the IdType entry where we can type in the type of the property (with the corresponding IntelliseSense).

8. Once the process is complete, we should end up with the following class (for the value “Customer”):

Classifying the Template

Currently the newly created template has been classified under “No Languages”. The main issue with this is that this template will be available pretty much everywhere, even places where it wouldn’t make sense to create a new class.

Let’s proceed in limiting it in scope and defining a category:

1. Select ReSharper | Live Templates and Click on Edit on the newly created template

2. Select the link at the top of the editor next to the “Available” text

The Template Availability dialog box will appear

3. Select the Language-Specific option and choose C# from the dropdown list. The dialog box should now change to show language specific options:

4. We can now choose the minimum version of the compiler for which this template is available (for example if it contains lambda expressions, we cannot use it versions below 3) and also choose where we want the declaration to be available. In our case we can choose Everywhere.

5. Last thing left to do is define a New Category for this template. We can do this by selecting it in the Live Templates tree, right-clicking and selecting New Category. In our case we would type C#

With this change we restrict where this template will be available and have a better classification when viewing templates.

Extending Functionality with Macros

We saw that when multiple instances of a variable appear in the template definition, as one changes, others will update to reflect that change. However, sometimes we might want a slight variation of a specific variable. Say for instance, we are create a template to define a property with a backing field (this template already exists by the way). In this scenario, usually the backing field name is the same as that of the property name with a lowerCamelCase. Let’s see how we can define a template like this using the Macros in the Live Editor Template:

1. Create a new template following the steps outlined previously, ending up with the following definition:

If we were to use this template as is, ReSharper would prompt us to enter a value for $className$, $IdType$ and $backingField$. Ideally what we would like is to have the latter to be a variation of the $className$, concretely, a lowercase version.

2. On the right side of the template editor, there is a Window that displays Macros that we can apply to variables. There is one for each variable. Click on the backingField entry and select the Choose Macro link

A dialog box appears giving us a series of operations we can perform on the variable, from suggestions, conversions, metadata, etc. In our case we need to scroll right to the end and select “Value of another variable with the first character in lower case”:

3. Once we click OK, the Macro window will then be updated to reflect the change and allow us to define the value of the variable. Click “another variable” link and select one className.

4. Save the template.

5. Invoke the template by typing “be” as before. We should end up with:

We can now type the className. As we do, we see that the backing field will automatically update to reflect the changes.

This is just a simple case of applying a Macro. We can have multiple Macros in the same template and combine them to achieve powerful templates.

Additional Template Options

At the top of the template editor, there are two additional check boxes:

The first one is used to indicate whether we want the template to be reformatted according to the defined styles we have set up in ReSharper once completed. The second option is useful when we are referencing namespaces that are not in the using directives. Let’s imagine for instance that we generate a template to spit out some Unit Test fixtures for NUnit. If we were to decorate the class with a [TestCase] attribute in a blank file, ReSharper would indicate an error saying the the namespace is not imported. The way to solve this issue is to fully qualify the attribute when defining the template and select this checkbox. ReSharper will then make sure it imports the correct namespaces and shorten the attribute.

Sharing Templates

Any template created under the User Templates is visible to the current Windows user for any solution. If we want to have templates specific to a particular solution, we would need to create them under the Personal Solution Templates. These however again are restricted to the current user. If we want them shared across multiple users we need to place them under Shared Solution Templates.

When it comes to sharing templates across machines with team members, the cumbersome way would be to export templates and have each team member import it. The preferable way is to place these templates under network drive and then mount them using the Mount File Storage

By doing this, ReSharper is aware that these templates are shared across machines and makes sure they are updated accordingly.

Summary

Live Templates in ReSharper offer us a lot of opportunities to be more effective when writing code. It is not about code generation but about not wasting time having to type repetitive things. It is also important to understand that they should not replace good programming practices. For example, using templates to write out repetitive code for logging is not the best way to approach the problem. A better solution would be to use Aspect Orientated Programming. However, there are many case where templates are very efficient. In future blog posts we’ll examine the Surround and File templates that ReSharper also offers us.

I don’t know why this post says you have to either export/import or use “Mount File Storage” in order to share templates across multiple computers. We just put ours in the “Shared Solution Templates”, and they get saved in the .resharper file, which goes into version control. So they’re shared just fine.

Just out of curiosity, though, what does “Mount File Storage” do? I’ve never noticed it before, and this post doesn’t actually say what it’s for or how it’s used.

Your solution is entirely valid. The Mount File Storage is just a path to a network share where you can store the templates. The difference from sharing them on a solution based is that these are across solutions. The only relationship they have with solutions is that they get updated when you open/close one.

I think you are answering a different question. My problem is not the path, but how I can easily create the xml-file to mount in the first place.

Exporting my existing, but unmounted, templates doesn’t work. When I mount that file, no templates shows up. Which is kind of strange, because why do you want two different file formats for the templates?