Announcing Scripty
I've written a lot of T4 templates, and while they work well enough for compile-time code generation, they're never much fun to write. Recently however I've noticed an even bigger problem with T4 templates now that Visual Studio is becoming less and less a required part of the build process (more on this in a minute). Thankfully, the Roslyn team has done an excellent job of packaging the Roslyn compiler into an easy to consume scripting package. By combining that scripting support with some Visual Studio extensibility, we can provide a code generation alternative that relies on Roslyn scripts written in plain old C# (VB.NET script support coming soon).
Using the .NET Compiler Platform in T4 Templates
T4 templates provide a powerful way to generate code at design time (and sometimes at compile time if you set up Visual Studio appropriately). The traditional way of accessing the code of your solution from within a T4 template is to get the Visual Studio API (called DTE). This has always seemed like a bit of a kludge to me and feels a little too far removed from the code and what it represents. We now have another option by using the .NET Compiler Platform from within a T4 template to parse, query, and output content based on the files in our solution.
A T4 Template To Get All CSS Class Names
This post combines two of my favorite things: meta-programming and the elimination of magic strings. The goal is to automatically generate a class with static const
strings containing the name of all the CSS classes in your CSS files. Why would you want to do this? There are a number of reasons. First, it helps eliminate magic strings from your view code. Instead of writing <p class="my-class">
you can write <p class="@Css.MyClass">
. It also helps when writing view code because you'll have access to IntelliSense data for all of your CSS classes, making it easier to remember their names and avoid mistakes. Finally, it improves analysis and refactoring because you can now rely on code engines to locate and operate on uses of a particular const string
instead of just plain-text searching.