Ok, I’m still at it and am still just at the surface of what is possible with Visual Studio Templates. Seriously. If you go look at PAG’s software factory stuff – they’re just putting out templates on steroids. Whatever disagreements I have in regard to how they write (overly complex) software, the factories are a great example of how far you can push things.
This time around I want to talk about adding code to our template. Adding code to a template is done by writing a class that implements the IWizard interface, GACing said class and then referencing it in your VSTemplate file. Simplicity itself!
Overview
The goal of writing a Wizard is to introduce more control over how our new project or item is created. Without being able to add some code we are stuck with the few parameters that Visual Studio has built in. While those parameters are great and all, I’m still stuck with an incorrectly names class file in my project! I also don’t have much control over my namespace. Oh, and the time is formatted wrong – just want the date. I’m sure there are a dozen other things I’d like to add, but for now let’s correct those few things.
IWizard
Before jumping in to the code we should look at the interface that needs to be implemented. To work with IWizard you need to add a reference to the Microsoft.VisualStudio.TemplateWizardInterface assembly and add add a using statement referencing Microsoft.VisualStudio.TemplateWizard. With that out of the way you can look at IWazard. IWizard defines 6 methods:
· BeforeOpeningFile
· ProjectFinishedGenerating
· RunFinished
· RunStarted
· ShouldAddProjectItem
The first four methods occur at the phases they are named after. Most of the work we do will be in RunStarted. You can read the MSDN docs here. For our purposes everything can be done inside RunStarted so I’m going to ignore the other members of the interface.
Inside RunStarted we are given the DTE object (automationObject), a dictionary of replacement parameters, the kind of Wizard we are (Project or Item) and then an array of custom parameters.
I’ve talked about working with DTE before. Everything I said this is true now. You can go in and access all of the Visual Studio environment and do whatever you want in there. In this case we don’t need anything fancy. We also won’t care about the Wizard kind here, the wizard we’ll put together will work regardless. The customParams won’t be used either. That leaves the replacementDictionary.
The replacement dictionary brings up the VSTemplate file I mentioned earlier. One of the sections in the file is for specifying a wizard to run whenever the template is used. Registering your template is easy enough. Just specify the assembly for your wizard and the name of the class. Here is the XML you’ll use:
Why they didn’t just do a full strongname is beyond me, but I’m not going to complain too much. The actual implementation of your template is also really easy. In the RunStarted method I’m going to throw up a dialog box and get the namespace and class name we want for our first class. When the user hits OK I put those two values in to the replacement dictionary and let VS do the rest . Here is the code:
Easy. However, renaming the actual file takes more work and involves using the VisualStudio objects. Even so, we now have a wizard that allows us to provide additional parameters to our templates. In this case I’m controlling the file’s namespace and class name with my own parameters. You could also use information collected inside your wizard to configure the project differently.
Conclusion
I still feel that I’m barely scratching the surface of what you can do with Visual Studio’s templates. In my next go around with them I’m going to introduce microsoft’s template engine to the mix so we can make some really kick ass templates.