Posts Tagged ‘code generation

01
Nov
07

Code Review: Subsonic Template.cs

Following the recent post, I started looking for similar projects, that made use for ASP as template generator. Quickly enough I found Subsonic.

Description

The Subsonic templating engine uses aspx file, but it would not pass through ASP.Net for rendering. Instead they parse and replace the appropriate ASP directives with their own facilities. They generate a ‘SuperTemplate’ source code, which they compile and then run – which produces the required source code.

Some snippets are required:

 

private const string HEADER = @”using System;

using System.Text.RegularExpressions;

using System.Collections;

using System.IO;

using System.Text;

using SubSonic;

using SubSonic.CodeGenerator;

using System.Data;

using System.Configuration;

using SubSonic.Utilities;

 

public class Parser#TEMPLATENUMBER#

{

public static string Render()

{

MemoryStream mStream = new MemoryStream();

StreamWriter writer = new StreamWriter(mStream, System.Text.Encoding.UTF8);

writer.AutoFlush = false;

 

;

 

private const string FOOTER = @”

StreamReader sr = new StreamReader(mStream);

writer.Flush();

mStream.Position = 0;

return sr.ReadToEnd();

}

}”;

This is the header of the supertemplate, which is later followed by all the aspx directive and content, translated to writer.Write() appropriately. So a <%= myprop %> would translate to writer.Write(myprop); in the body.

For that they have several neat rules (snippet):

 

templateInputText = ParseTemplate(templateInputText);

templateInputText = Regex.Replace(templateInputText, @”<%=.*?%>”, new MatchEvaluator(CleanCalls), RegexOptions.Singleline);

templateInputText = Regex.Replace(templateInputText, @”<%%>”, string.Empty, RegexOptions.Singleline);

templateInputText = Regex.Replace(templateInputText, @”<%[^=|@].*?%>”, new MatchEvaluator(CleanCodeTags), RegexOptions.Singleline);

 

private static string CleanCalls(Match m)

{

string x = m.ToString();

x = Regex.Replace(x, “<%=”, “\t\t\twriter.Write(“);

x = Regex.Replace(x, “%>”, “);”);

return x;

}

A nice shortcut:

public class TurboTemplateCollection : List<TurboTemplate>

{

}

In the end this text is being compiled and run, result with text. All in all the clarity of the code is very good, and I liked the concept of generating such a ’super-class’ in a meta-class kinda way — a class that generates new classes textually.