One of the advantages of ReSharper Live Templates (LTs) over ordinary Visual Studio snippets is that macros may contain execution instructions. In other words, your LTs can execute code .Net code when being invoked. This code can do something simple (e.g., insert current date and time) or it can do something complex, like pop up a drop-down list with different guid formats:
In case you’re wondering, macro invocations are defined in the Live Template editor – you simply pick a variable and select the macro associated with that variable:
As you can see from the above screenshot, ReSharper has lots of predefined macros, but you can also define your own. A macro is basically a class that
- Implements the IMacro interface
- Is decorated with the Macro attribute
For example, the CurrentFilePathMacro from the ReSharper PowerToys is defined as follows:
The MacroAttribute lets you specify metadata for the macro, specifically its name (which should be unique), as well as long and short descriptions of what the macro actually does.
Now let’s talk about the IMacro interface. This interface has five members:
- Parameters is a property that defines parameters that can be passed into the macro. For example, if your macro creates a field name for a property name, the field name would be a parameter. If your macro doesn’t need any parameters, simply return EmptyArray<ParameterInfo>.Instance.
- GetPlaceholder() is a method that defines the placeholder value. Most ReSharper LTs typically put an "a" there.
- GetLookupItems() returns the list of ‘hotspot’ items that will be displayed at the placeholder. A hotspot refers to the elements in the template that are placeholders, whether they are editable or not.
- EvaluateQuickResult() is called every time a hotspot obtains a value. Often the value of one hotspot can influence that of another. For instance, assume a a macro that provides information on MVC Controllers. Based on the selected controller, the next hotspot which could provide information on Actions would vary. By implementing this method we can update this information. If no additional processing is required, null is returned.
- Evaluate() is called upon the acquisiiton of the final result. Quite often, EvaluateQuickResult() also yields the Evaluate() value by calling it directly.
- HandleExpansion() is used to perform extra activities on a hotspot. For instance when navigating to a different hotspot. If no additional processing is required, we return false.