T4 Multiple File Outputs in a .NET Core Project
I recently needed to auto generate boilerplate classes for a project based upon reflection meta data. Having been a few years since I’d leveraged T4 for SQL Stored Proc generation and the awesome T4MVC template, surely there’s a shiny new method?
Scripty comes up as an alternative scripting approach for code generation, unfortunately it’s having major issues with VS 2017 and the Roslyn compiler.
So, it looks like T4 Templating is still the way to go. However whilst writing the template, it appears that splitting code into multiple files and moving directories is quite a problem as templating standard behaviour is to nest files under the parent template.
First, we’re going to leverage the T4 Toolbox extension. Yes, this works in VS 2017 at the time of writing (I have update 15.8.9), you can find this here.
So our strategy here is to have a Runner template and code generation template.
- Runner template – This will be responsible for initialisation of the code generate template, our method is to enumerate through a collection and pass data to our template
- Code generation template – This will contain our templating code
Please note – The below represents a basic example, and is not production code.
Lets go through the code above:
- #A – We want to ouput .cs files, also we’ll need those namespaces to import the required classes for enumeration/file reading
- #B – Here we instantiate our code generation template, in this example it’s a template which generates a blank Web API controller
- #C – Since the templates base directory at runtime is within a sub directory of your VS folder, we need to do a little configuration, for this example we want to read a text file in our bin folder
- #D – Reading of a text file
- #E – We pass a few strings to own code generation template, since these will be the subject of said class
- #F – We call the RenderToFileMethod, passing a file path for our class
- #A – Here we’ll leverage the helpers which T4 Toolbox providses, therefore you’ll in to include the file
- #B – We’ll want to inherit from the abstract class
CSharpTemplatewhich is part on the T4 toolbox. In our derived class we’ll access the
TransformTextmethod in the base class to append our additional code
You can have multiple code generation templates which are used within a single template runner, however it increases the scope of a problem occurring in the transformations, and therefore a 1:1 ratio is better.