# Saturday, February 20, 2010

T4 Templates are really nice given that the tools are included free in Visual Studio (the Express Editions of Visual Studio appear to have some under-documented limitations when it comes to T4 support).

The primary way that T4 templates are processed is from within Visual Studio.  That works pretty well.

What if you want to process a T4 template outside of Visual Studio (as part of an automated build process, for example)?

The easiest option for running a T4 template outside of Visual Studio is through the TextTransform.exe (custom T4 host) command line tool.

The main difficulty I've encountered using the TextTransform.exe command line tool is error handling.

Here's a sample error (written to StandardError):
--
MyT4Template.tt(0,0) : error : Running transformation: System.InvalidCastException: Unable to cast object of type 'Microsoft.VisualStudio.TextTemplating.CommandLine.CommandLineHost' to type 'System.IServiceProvider'.
   at Microsoft.VisualStudio.TextTemplatingc7fe0d0277b54f7c95c25936373918ff.GeneratedTextTransformation.TransformText()
--

Notice the (0,0).  That is where the line and column numbers would normally go for where the error occurred.  Also notice the stack trace contains no useful information (the error message, at least, in this case *is* useful).

The other downsides of using TextTransform.exe are similar to situations where you are calling out to an EXE file from code as opposed to working against an API.

The main positive I've encountered using the TextTransform.exe command line tool is if the template processes okay in Visual Studio, it will likely process okay using TextTransform.exe.  The above error was generated by using a template that tried to reference EnvDTE.DTE which works fine from within Visual Studio, but doesn’t necessarily make sense to do outside of Visual Studio.


As an alternative, you might attempt to use the Visual Studio T4 engine from .NET code like so:
--
ITextTemplatingEngineHost host = new Microsoft.VisualStudio.TextTemplating.VSHost.TextTemplatingService();
ITextTemplatingEngine engine = new Microsoft.VisualStudio.TextTemplating.Engine();
string outputCode = engine.ProcessTemplate(inputContent, host);
--

But that won't work.  You will get these compile time errors:
--
The type 'Microsoft.VisualStudio.TextTemplating.VSHost.TextTemplatingService' has no constructors defined
'Microsoft.VisualStudio.TextTemplating.VSHost.TextTemplatingService' is inaccessible due to its protection level
--


The hardest option for running a T4 template outside of Visual Studio is by implementing the ITextTemplatingEngineHost interface.  There is an example of how to do that here:

Walkthrough: Creating a Custom Text Template Host

The problem with that example is that it fails for multiple distinct reasons for templates that run just fine in Visual Studio and from TextTransform.exe.  It doesn’t appear to be even close to a full featured ITextTemplatingEngineHost implementation (it’s quite a "teaser" of a sample, enough to show it has potential, but not enough to show you how far from reality you are).

Mono provides an alternative implementation of the ITextTemplatingEngineHost interface here:

http://anonsvn.mono-project.com/viewvc/trunk/monodevelop/main/src/addins/TextTemplating/Mono.TextTemplating/Mono.TextTemplating/TemplateGenerator.cs

And while that fails less often on templates that run just fine in Visual Studio, it still fails in multiple ways.  I appreciate what the Mono folks have done, but for this use case (trying to run T4 templates outside of Visual Studio), there isn’t much value add.

The advantage of using a custom ITextTemplatingEngineHost host implementation is you have significantly more power and control than you have with TextTransform.exe.  TextTransform.exe has a limited input/output/error mechanism and its internals are not very extensible/customizable.

The disadvantage of using a custom ITextTemplatingEngineHost host implementation (as opposed to TextTransform.exe) is that you possibly have to write a decent amount of code against an undocumented system before your T4 template that processes fine in Visual Studio will process equivalently from .NET code (this will depend greatly on the contents of your T4 template).

If anyone is aware of other (free or commercial) custom implementations of the ITextTemplatingEngineHost interface that are usable from .NET code, please let me know!

Update March 7, 2010: Apparently this will be much easier in Visual Studio 2010:

Generating Text Files at Run Time by Using Preprocessed Text Templates

Saturday, February 20, 2010 3:09:50 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  |