Introduction
Most developers I've met and talked to throughout my career have shared one thing in common:
their interest in solving problems and their disdain of the mundane. Boring, repetitive tasks
are the bane of the development world, so much so that oftentimes programmers will spend countless
hours constructing a solution that relieves them from some mundane chore, even if the time
it takes to build a workaround is longer than the time that the boring task would require!
A common "bore chore" in development is hammering out similar code, a task good IDEs will
eliminate. For example, when using Visual Basic in Visual Studio .NET, typing out:
Public Property PropertyName As Type
Will automatically expand into:
Public Property PropertyName As Type
Get
End Get
Set (ByVal Value as Type)
End Set
End Property
Unfortunately C# doesn't provide such automatic expansion. Furthermore, there are more specific
scenarios that you may need to implement that Visual Studio .NET does not handle by default.
Fortunately Visual Studio .NET provides a way to create your own expansions, in a round-a-bout way:
through the use of macros. Macros are short pieces of code you can write that interact
with the Visual Studio .NET environment. In this article we'll look at how to create macros
to eliminate repetitive typing for a task common to custom ASP.NET control developers -
creating property statements that use the ViewStateStateBag as
a backing store. Read on to learn more!
An Introduction to Visual Studio .NET's Macros
Macros are an old concept in computer applications with their roots in office productivity
software applications like Excel. Essentially a macro is a set of instructions that a user
can record and repeat at some later time, enhancing productivity since the sequence of steps
can be repeated with a single click of a button. Macros, in their simplest sense, can be
recorded through a user's interaction with the GUI environment. More advanced macros can be
created by writing code, meticulously spelling out the steps of the macro.
Visual Studio .NET allows for both simple, recorded macros, as well as programmatically-created
macros. To work with macros explore the Macro submenu, which is found under the Tools menu in
Visual Studio .NET (seen the screenshot to the right). You can record a macro through the GUI
via the Record Temporary Macro. To create a macro programmatically, choose the Macros IDE.
The Macro Explorer lists all of the Visual Studio .NET macros that can be run.
This article examines how to create macros programmatically. Macros recorded through the GUI
are easier to create, as they require no programming, but allow for less flexibility. Plus
writing code is more interesting and, as you'll see shortly, not difficult. Additionally, the
temporary macros are, as their name implies, temporary, and must be explicitly saved. For
more information on recording Visual Studio .NET macros through strictly GUI interaction,
refer to Matthew MacDonald's article, Using
Visual Studio .NET Macros.
Programmatically Creating Visual Studio .NET Macros
To create a Visual Studio .NET macro programmatically, launch the Macros IDE by going to the
Tools menu, selecting the Macros submenu, and choosing the Macros IDE menu item. The Macros IDE,
which is
shown below, looks similar to the standard Visual Studio .NET IDE. On the left is the Project Explorer,
which lists the Macros in the system. (These Macros can also be viewed from the standard Visual Studio
.NET IDE through the Macro Explorer - Tools --> Macros --> Macro Explorer, or Alt+F8.)
The Project Explorer consists two projects by default - MyMacros and Samples. The Samples projects
contain a number of sample macros, which can be useful to learn the source code and syntax from.
To create a new macro right-click on the MyMacros project and choose to add a new Module.
The macros created through the Macros IDE can be executed via the Macro Explorer in the Visual
Studio .NET IDE. The Macro Explorer, shown to the left, displays a tree showing the various
macros. At the top level are the macro projects - MyMacros and Samples. The Samples macro node
is expanded, showing the modules of the Samples macro project node - DevStudio6Editor, MadeAddin,
Utilities, and so on. Expanding a macro module node lists the module's public subroutines. To
run one of these subroutines, simply double-click the appropriate node.
Creating a ViewState Property Macro
To practice creating a macro, let's build a real-world macro for creating a boilerplate
property statement that custom ASP.NET server control developers will find useful. If you have
created custom, compiled ASP.NET server controls before then you know that when creating properties
for your control it's important that they read and write to ViewStateStateBag
as opposed to a private member variable. That is, properties in a custom, compiled ASP.NET server
control should have a syntax like:
' VB.NET...
Public Property PropertyName As Type
Get
Dim o as Object = ViewState("PropertyName")
If o Is Nothing Then
Return Default_Value
Else
Return CType(o, Type)
End If
End Get
Set (ByVal Value as Type)
ViewState("PropertyName") = Value
End Set
End Property
// C#
public TypePropertyName
{
get
{
object o = ViewState["PropertyName"];
if (o == null)
return Default_Value;
else
return (Type) o;
}
set
{
ViewState["PropertyName"] = value;
}
}
To create the property statement we need to use to specify three bits of information -
the property name to use, its type, and the default value. Our macro will work as follows: the
page developer will type in on a line the property name, type, and default value, each separated by
a space. For example, to create a string property with the value FirstName and a default value
of "Scott", the page developer would type into the VS.NET IDE: FirstName string "Scott".
Next, to create the property statement, the page developer would highlight the string they just entered
and run the macro. The macro would then delete the page developer-entered string and replace
it with the appropriate property syntax.
To accomplish this start by creating a new macro in the Macros IDE named ViewStateMacros.
(Right-click on MyMacros and opt to add a new Macro.) We will be creating two public subroutines:
CreateSimplePropertyVB() - generates the property syntax for Visual Basic .NET for each
of the selected, properly-formatted strings. (Property_Name Type Default_Value)
CreateSimplePropertyCSharp() - The same as above, except generated C# syntax.
When creating a macro you have programmatic access to the Visual Studio .NET IDE. The TextSelection
object, for instance, provides information about the selected text in the IDE, and allows you to
programmatically delete, edit, or inject text into the IDE. We'll use this object to determine
the highlighted Property_Name Type Default_Value syntax, as well as delete this selection
and insert the appropriate syntax based on this markup.
Let's examine the CreateSimplePropertyVB() subroutine. As the below code shows, it
starts by retrieving information about the current selected text and divides up each separate line
into a string array, Lines. Next it iterates through each string in the array, concatenating
the property syntax to a string, which is eventually inserted into the IDE.
Private Function GetSimplePropertyVB(ByVal line As String) As String
'Make sure we are dealing with selected text in the form of:
'Variable_Name Type Default_Value
Dim Words() As String = line.Trim().Split()
Public Sub CreateSimplePropertyVB()
Dim TS As TextSelection = DTE.ActiveDocument.Selection
Dim Insertion As String, Line As String
Dim Lines() As String = TS.Text.Split(vbNewLine)
For Each Line In Lines
Insertion &= GetSimplePropertyVB(Line)
Next
TS.Delete()
TS.Insert(Insertion)
End Sub
As you can see, the macro is pretty simple. It just squirts out the appropriate text based
on the inputs entered by the user. The screenshots below show the macro in action. (The macro source
for the C# syntax is provided at the end of this article.)
Entering the property name, type, and default value...
The results after the macro has been run...
Conclusion
In this article we saw how to use macros in Visual Studio .NET to automate repetitive tasks.
Macros allow you to programmatically spell out the mundane tasks that can then be executed at
the click of a button. This article provided the macro code needed to automatically create a
ViewState-backed property statement commonly used when creating custom, compiled ASP.NET server
controls.