Inspecting Class Properties from a T4 Template

I wanted to write a T4 template to find all the properties inside one of my C# classes, which would allow me to auto-generate some code. After that, if I added another property the code should automatically update - and I would have one less thing to remember.

The solution I came up with involved using the C# compiler from inside the T4 template. The template actually builds an in-memory Assembly and then reflects over the compiled class to find it's properties. Then you can do whatever you like with them in the output. So here is an example project using that approach.

This means that you only need to do something like this:

string path = this.Host.ResolvePath("");
string file1 = Path.Combine(path, "MyClass.cs");
string file2 = Path.Combine(path, "MyClass2.cs");
Parser p = new Parser(new string[] { file1, file2 }, "T4ClassProperties.MyClass");
p.WriteProperties(WriteLine, formatter);

...and provide an extra function to format the output how you want it, like this:

string formatter(string s)
   return(string.Format("Console.WriteLine(\"- {0}\");",s));

The example I've given makes a C# method that outputs the names of all the properties in a specified class to the console. But in reality I have used it to do things like build MVC3 razor views automatically.  To do that you'd just need to tell the template to output a .cshtml file instead.

The limitations are that the class file you are inspecting needs to compile stand-alone, or you need to be able to pass an array of source file names that will enable the class to build. You also have to specify any special assembly references, which I have not shown in this example, but is supported by my template. Also, to make it automatic, you need to get the T4 template to run as a part of the build process. So I've hacked the project file to run a "BeforeBuild" target in this example.

As you can see, all the magic happens inside, which you simply reference in your own template with something like:

<#@ include file="" #>

I thought that it might be worth blogging this, since it might come in handy again one day. I'm only looking at *properties* ... but it could be adapted to look at methods or anything else you can access via reflection...

[NOTE: if you'd like to know more about using T4 with MVC3, then you might to take a look here.]