Code Generation in Download Tracker

One of the things that I need in Download Tracker, but have not yet implemented, is a collection of Download objects. You’ll recall that an individual Download object in the DownloadEngine project represents a file downloaded from the Internet, together with the metadata that Download Tracker allows the user to add. A matching collection will let me work with more than one Download object as a group. This will come in useful when I’m ready to return a set of search results from the core engine back to the user interface layer. Of course, I could just use a simple Collection class for this, but I’d like some other features:

The collection should be sorted so that I can return it in a particular order.

The collection should only accept objects of the Download type.

This second requirement is just good coding practice. If I use a strongly typed collection, then I’ll get additional IntelliSense as I’m developing the application, and I’ll be protected against a whole group of silly errors that can result from putting the wrong object into the wrong collection.

If you poke around the VS .NET help, you’ll find a walkthrough on creating your own custom collection class. This ends up requiring a fair bit of code to do right. The code is also rather repetitive; once you’ve written one strongly typed collection class, it’s not an exercise that you want to repeat every time you need another such class. This makes developing such classes an ideal situation for code generation.

Fortunately, CodeSmith already includes a template for a strongly typed, sorted collection. By using this template, I can create the collection that I need with little effort. I’ll use Code-Smith’s VS .NET integration to make this easier.

TECHNOLOGY TRAP: The Velvet Straightjacket

Many code generators available for .NET are all encompassing. They work by letting you specify things about your application, such as the tables where data is stored and the general layout of ASP.NET pages, and then build the entire application for you from your specification. While this can save you a tremendous amount of time and repetitive programming, it can also lock you in to a particular tool if you’re not careful.

When you’re using one of these comprehensive code-generation systems, make sure you understand the extent to which you’re committed to keep using it. What happens if you need to add another developer to the project? What happens if you have to make custom changes to the user interface? What happens if you’re ready to upgrade to a new version of .NET but the tool hasn’t been revised yet?

Considering the expense of these tools, it’s worth doing a serious evaluation before purchasing. When you do so, look not just at whether the end product fits your needs but at how it’s implemented. To avoid getting trapped in the future, the generated code should let you make changes easily—and should be easy to remove from the tool if you later decide that the project should stand on its own.

The first step is to add the template, CSSortedList.cst, to the DownloadEngine project. You can add any file you like to a project in VS .NET (though of course the program doesn’t really know anything about .cst files, which means you won’t get color-coding or IntelliSense if you work with the file in this interface). This particular template comes from a source that I trust, but even so, I spent a few minutes reading through it to get a sense of how it works.

The template is a necessary part of the process, but there are also some properties that I need to specify when building the actual Downloads class. CodeSmith handles this by letting you define a property set as an XML file. I added a new XML file, Downloads.xml, to the project with this content:

Note that the CodeSmith XML syntax allows you to define multiple property sets within a single XML file. If I needed several strongly typed collections in this project, I could define them all with a single file. The property set itself is simply a list of values that the template needs to do its work; these are the same values that I would fill in manually if I were using the CodeSmith user interface.

The key to making this work is to set the CustomTool property of the Downloads.xml file to CodeSmithGenerator. This tells VS .NET to invoke the CodeSmithGenerator tool every time that the file is saved, and to use the file as input. The result is that as soon as I save the Downloads.xml file, I get Downloads.cs as a hidden file in my source code tree.

The final step is to get the correct files into my source code control system. In this case, I’ve checked in CSSortedList.cst and Downloads.xml, but notDownloads.cs. That’s because the first two files contain all of the information necessary to rebuild the third, so there’s no point in putting the third file into the system separately.

RULE

Put code-generation source files, but not code-generation result files, under source code control.