|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionOne of the measures of my efficiency as a developer is how quickly I can spit out well-written, verified code. This challenge is typically met with many mechanisms: code generation programs, code snippets and even the rudimentary cut & paste. In this article, I want to talk about Visual Studio code snippets and the generative snippet mechanism which I use in order to squeeze the maximum value out of snippets. I will also present a showcase of some of the generative snippets I use in everyday work. Basic Introduction to SnippetsA code snippet is just a chunk of code that you can enter quickly because typing it by hand for the Nth time can be rather boring. Here is an example of one such entry: #region INotifyPropertyChanged Members /// <summary> /// Notifies the caller when a property is changed. /// </summary> /// <param name="propertyName">Name of the property.</param> protected void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } /// <summary> /// Occurs when a property is changed. /// </summary> public event PropertyChangedEventHandler PropertyChanged; #endregion To get the above code to appear in VS, I just type a magic combination of letters ( Some snippets allow you to customize them, i.e., edit parts of them after the snippet has been injected. To allow for this, VS will show placeholders for variables that can be edited. The user can then use the Tab character to move from one placeholder to another. Here’s how it typically looks:
Generative SnippetsThe above mechanism, as I’m sure you’ll agree, is not very powerful. I mean, it’s useful for tiny little things that you can inject, but the problem is that you cannot execute C# inside the snippet – in fact, Visual Studio does provide 3 functions that you can execute, but these functions are of little use to us. What I wanted to do with snippets is make them parameterized. For example, I want to type in How Is It Done?The API for generating snippets is really simple. In fact, the following diagram pretty much sums it up:
Code snippets are defined in XML, and the above classes are, basically, objects that help generating this XML a little easier. On the top level, we have the Here's a short guide on how to write your own snippets. First, we define the snippet collection:
var sc = new SnippetCollection();
Then, we put as many iterative loops as we require for our snippets. I'll just use one, with a counter from 1 to 10. Inside the loop, we create the for (int i = 2; i < count; ++i) { var s = new Snippet { Author = author, Description = "Creates an inline multiplication equivalent to Math.Pow(…, " + i + ").", Shortcut = "pow" + i, Title = "pow" + i }; Literals can be added by explicitly instantiating the s.Literals.AddLiteral("x", "Variable name"); Now that we've added our literal, we can use it by typing var sb = s.CodeBuilder; for (int j = 1; j <= i; ++j) { sb.Append("$x$"); if (j != i) sb.Append("*"); } Now, before exiting the loop, we add the snippet to the snippet collection. sc.Add(s); Finally, once we are done with all the loops, we save the snippet collection itself. sc.Save("pow");
You might need to tweak the ShowcasePresented below are examples of some of the generative snippets included with the source code. Please note that some examples produce far too much code to be shown here, so I'll provide a textual description instead. arglistXCreates a list of comma-separated variables with a common name followed by a 1-based index:
arrayXCreates a declaration of an array with X elements. All elements are initialized to the same value
arrayXbyYCreates a declaration of a 2D array with X×Y elements. All elements are initialized to the same value, but for square arrays, the diagonal can be initialized separately. Note also that code for these snippets will not be reformatted correctly by Visual Studio.
forCXCreates X inset
parrXAdds a code stub to run X pieces of code in parallel. Uses
catchXAdds code to catch X different types of exception. Probably the most boring snippet of them all.
flagsXCreates a
getflagsXTests for X flags in an enum, and creates X boolean variables.
nulltestX
Test a chain of X properties for
powXInlines a power calculation instead of using
polyX & polyPXThese two snippet sets both manufacture member functions that compute a polynomial with highest degree X. The difference is that
varlistXDeclares X variables (variable names starting with ‘a’) in a single line of code.
fsmXCreates a finite state machine with X states. This includes declaration of the fsm enum, creation of Before- and After- subX & supXToy snippets that create subscript and superscript characters. They work in the Consolas font. The main purpose is being able to avoid opening the Character Map while trying to embellish your comments with clever little sub/superscript symbols. A demo cannot be presented here – try it out in Visual Studio. Entity snippetsEntity snippets create ready-made entity classes. There are several types, with different levels of infrastructure support. Here is a short list of the ones we have so far:
ConclusionGenerating snippets is one of the many ways in which one can easily create parameterized code generation. Though the results achieved are fairly simple, there are situations where this amount of flexibility is sufficient to get the job done. So if this article got you interested, check out the snippets (and the source code) and let me know what you think. You can leave comments here or on the CodePlex project page.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||