Sunday, September 06, 2009

Community Generation Harness

Community Generation Harness Released
 |  Kathleen Dollard  |  #    |  Comments [3]  | 
 Friday, September 04, 2009

Why is a Preprocessed Template the Coolest Thing since Sliced Bread

OK, really, it’s cooler than sliced bread.

When you create any file in Visual Studio you have the option to run a custom tool. Visual Studio and add-ins use this tool to do extra work – often generating a dependent file. In Visual Studio 2010, if you create a T4 template there are two options for the custom tool that runs.

 

Option 1 – Text Template

This style is consistent with VS 2008 and the DSL Toolkit.

The plain style of T4 templates evaluates the template places the result as an output file. If you create a T4 template that is “Hello World” you get a dependent file with the specified extension that contains “Hello World”.

There are two steps of metadata to artifact transformation going on here. First, the template is transformed into normal .NET code. This code is emitted and run to produce the result. The result as a string is output into the file you see.

There are two transformation steps and two .NET compile steps (although the full compile of your output is delayed in C#). For example, if you output “Hello World” as a C# code, it’s not legal code so you get a compile error. You can also create templates that have .NET errors in the code of the template, and this creates errors in the interim emitted code when it is compiled.

 

Option 2 – Preprocessed Text Template

The second option is to create a preprocessed template, which uses a different custom tool than the text template. This custom tool does the first step – creates .NET code which when run will create your output. This code is output as the dependent file. If you create a “Hello World” template, you’ll see a bunch of gunk that runs the template and a TransformText method. Within the TransformText method, you’ll see GenerationContext.AppendLine(“Hello World”).

The class contains a good deal of additional gunk which frees the base class. You can inherit from any class you want. You can define the alternate base class either with the inherits attribute of the template directive, or in a separate partial class.

You need external code, a template harness of some sort, to create your actual output. This is very simple code: it creates an instance of your templates class, runs the TransformText method, and outputs the result to a file. More on harnesses coming here soon.

You can also define additional code in a partial class for your template. This can include attributes, such as MEF attributes. It can also can include properties that can be set from the outside when the template is run, or attributed to be automatically filled with MEF.

This is VS 2010 Beta 1 behavior. The code output as the preprocessed template will change significantly in Beta 2. A logical enhancement would be including support for a parameter directive which would automatically create this property for you. You’ll still have to supply data.

 

Why are Preprocessed Templates this so Cool?

The primary reason is that they let you get your hands on that emitted code. This is the code that actually runs, and code which frequently will contain compiler errors because of some dumb thing you do in the template. Often, the T4 engine correctly backtracks these errors into the template, and/or provides enough debugging. But both of these tasks sometimes come up short leaving you with a compile or debugging challenge. I also frequently drop into this code to take advantage of native Intellisense, then copying the code back into the T4 template.

It also makes running the T4 template much easier.

If you’re running within Visual Studio directly to get output, you’ll find many challenges around accessing your metadata. While the T4 Toobox on CodePlex.com does an amazing job circumventing these issues, it results in complex brittle templates that have a serious separation of concerns issue as they simultaneously access metadata, manage and output files, and define output code.

Instead, you can run templates through a harness of some type. This makes the process similar to that using tools such as CodeSmith or CodeBreeze. Unfortunately, the design of T4 and the single file generator that is used by Visual Studio combine to make writing a T4 harness for plain T4 templates extremely challenging and just mucky.

Preprocessed templates redefine this process. The preprocessed code is a normal .NET class and the harness calls its TransformText template like any other .NET code, grabs the string, and outputs the file. Outputting multiple files is simple, and the harness can adopt additional sophistication, such as MEF provided metadata or overwrite protection.

 

Eleven Great Things about Preprocessed T4 Templates

The first great thing about T4 preprocessed templates is that you get a syntax check on save, and a full compiler check as soon as you run the compiler (or on save in VB). With traditional templates, you know about problems in the template when you attempt to output code.

The second great thing about T4 preprocessed templates is that you have access to a base class. A custom base class can manage all the metadata for a family of templates using the same metadata and significantly improve reuse.

The third great thing about T4 preprocessed templates is that you have a partial class for any additional code or class attributes you might want to include.

The fourth great thing about T4 preprocessed templates is that they make writing a harness for T4 templates a few order of magnitude easier – making it very simple to do.

The fifth great thing about T4 preprocessed templates is that you can include T4 transformations within your application. It’s just .NET code – you can run it whenever, however, why-ever you want. This means T4 templates are not just for code anymore. You can use them for any metadata to artifact generation, such as form letters, as long as you can recompile and redeploy template changes. MEF can help here as well because you just need to distribute small dlls with the changes and variations.

The sixth great thing about T4 preprocessed templates is that they run equally well in the main .NET framework and Silverlight. Or even mobile.

The seventh great thing about T4 preprocessed templates is that they are easier to debug. You have access to the code that will actually run, allowing you to debug the actual failing code, not the T4 template from which that code was derived.

The eighth great thing about T4 preprocessed templates is understanding what’s really happening when you run your template code. The logic of your template can sometimes be obscured by the overlay of T4 template logic and output code logic. The preprocessed code let’s you better understand the logic you wrote into your template.

The ninth great thing about T4 preprocessed templates is that you can get Intellisense directly within the preprocessed output, regardless of the AddIns you have in play.

The tenth great thing about T4 preprocessed templates is that they are NOT restricted to .NET 4.0. By down-targeting the preprocessed output, you create a dll which can be run in any appropriate version of the .NET framework. A .NET 3.5 harness can easily run preprocessed templates. You ONLY need the VS 2010 Beta when you are altering templates. The rest can be done on machines running only VS 2008.

The eleventh great thing about T4 preprocessed templates is that they remain T4. They use the same simple ASP.NET template style. Microsoft is making an increasing commitment to T4 with its use in LINQ to Entities, and MVC. I anticipate T4 will crop up in many additional tools from both within in and outside Microsoft – with CodeBreeze already making a commitment to support it in the next version.

You can get a different take on preprocessed templates on the Clarius blog here and here.

 |  Kathleen Dollard  |  #    |  Comments [3]  | 
 Tuesday, September 01, 2009

Welcome

Wow, I’m starting my second blog!

I plan to continue blogging about general .NET stuff and new technologies like Workflow and MEF on my personal blog at www.msmvps.com/blogs/kathleen. But I want to consolidate the code generation posts along with the AppVenture Community Generation Harness in a single location. My goal with this harness is to let it grow into an open source tool, and share the thinking behind it. I think the best location for this is the AppVenture site.

For clarity, AppVenture has two tools (which is not in itself very clear). AppVenture Foundations is our core tool which we use in business partnerships/consulting/etc. I’m very proud to be associated with this tool which pushes boundaries in interesting ways.

But both personally and with the full support of the rest of the AppVenture leadership team we want a tool available that offers a jumping off point for industry wide evolution of code generation. We think the community tool is an important first step.

I also plan to generally use this blog to post slides and sample code from user group talks.

Welcome!

 |  Kathleen Dollard  |  #    |  Comments [0]  |