I've been meaning to look into PowerShell for a while - it's been on an ever-growing list of things I'd like to learn more about. Recently I got around to spending some time with it and decided an interesting way to learn a little would be to create a module that allowed you to format objects using the Razor Engine.
Edit: When writing this article, I forgot to mention you need to make Powershell run .NET 4 to be able to use Razor. I did this by creating powershell.exe.config and powershell_ise.exe.config files as explained here.
The goal of the module is that you would be able to pipe some objects inand pass some template text, like this:
Ok, so this sample isn't particularly useful, but you should get the idea. The string passed in could be read from a file, and the output could be written to a file. This will allow you to format objects using Razor, which I think it is a pretty cool templating language.
When I opened PowerShell ISE to start coding, I actually expected this to be only a line or two of code, but it turned out to be a little more complicated. Because Razor compiles to code, and you'd likely only want to do this once regardless of how many times the template would be used, it's not as simple as just passing an object and a template into Razor. First we had to create the Razor Engine:
This sets up the Razor Engine with some fairly basic settings, including the name and namespace of the generated class, and also the base class. The base class is required to have a few things for Razor to be able to use it:
A virtual Execute() method
A Write(object) method, called when Razor outputs a variable/expression
A WiteLiteral(object) method, called when Razor outputs literal content from the template
Because it's not trivial (or certainly, I couldn't find a way) to create a class inside PowerShell, I cheated a little bit. To avoid including a binary .NET assembly, I compiled the base class from a string on the fly:
This code first compiles the base class into an assembly, and then calls Razor to generate its own code, which is then compiled with a reference to the first assembly, which contains the base template class.
Finally, we create an instance of the Razor-generated class which we'll finally use for the transformation:
To perform a transformation, all we need to do is set the Model property on the Template, and then call the Execute method:
And that's it, now we can format our objects using a Razor template, as shown earlier: