T4 Code Generator - Create Resource Helpers

by Jacobus Meintjes December 07, 2009 22:35

With Visual Studio comes the T4 code generator, and I have been reading about it today. While reading online and trying it out, I created a resource helper template. What this template does is scan the current folder for all resource files and creates a static helper class to allow easy access to the resource variables without having to update code for the resource manually every time.

This is not a standard feature of Visual Studio, but you can download T4 Editor and T4 Toolbox to assist with templates and syntax highlighting.

Starting off, you will need to create a project and add the resource files. Then you need to add a text file, renaming it, to "ResourceGenerator.tt". The .tt extension lets the IDE know this is a custom generator file.

The first line of the file will consist of

   1:  <#@ template language="C#" HostSpecific="True" #>

HostSpecific="True" as explained on MSDN: "If you set the value of this parameter to true, you can access a property called Host in your text template." We will be using Host to retrieve the current project folder.

Then comes the normal C# using directives, with a slight difference.

   1:  <#@ import namespace="System.IO"#>
   2:  <#@ import namespace="System.Text"#>
   3:  <#@ import namespace="System.Text.RegularExpressions"#>

Next we start with the code

   1:  <#
   2:  string baseDir =  Host.ResolvePath("");
   3:  CreateResourceManagers(baseDir);
   4:  #>

<# and #> specifies code blocks

Then the bulk of the code to complete this demo.

   1:  <#+
   2:      public static void CreateResourceManagers(string dirPath)
   3:      {
   4:          DirectoryInfo directoryInfo = new DirectoryInfo(dirPath);
   5:   
   6:          foreach(FileInfo file in directoryInfo.GetFiles("*.designer.cs"))
   7:          {
   8:              string resource = string.Empty;
   9:              StringBuilder sb = new StringBuilder();
  10:              using(StreamReader reader = new StreamReader(file.FullName))
  11:              {
  12:                  resource = reader.ReadToEnd();    
  13:              }
  14:   
  15:              Regex pattern = new Regex(@"internal class (?<className>S*)");
  16:   
  17:              Match match = pattern.Match(resource);
  18:   
  19:              string className = match.Groups["className"].Value;
  20:              string fileName = className + "Helper.cs";
  21:   
  22:              sb.AppendLine("using System.Threading;");
  23:              sb.AppendLine("using System.Globalization;");
  24:              sb.AppendLine();
  25:              sb.AppendLine("namespace T4Demo.Resources");
  26:              sb.AppendLine("{");
  27:              sb.AppendLine("public static class " + className + "Helper");
  28:              sb.AppendLine("{");
  29:              sb.AppendLine("private static readonly CultureInfo ResourceCulture;");
  30:              sb.AppendLine();
  31:              sb.AppendLine("static " + className + "Helper()");
  32:              sb.AppendLine("{");
  33:              sb.AppendLine("ResourceCulture = Thread.CurrentThread.CurrentCulture;");
  34:              sb.AppendLine("}");
  35:   
  36:              pattern = new Regex(@"internal static string (?<property>S*).*[{]");
  37:   
  38:              match = pattern.Match(resource);
  39:   
  40:              if(match.Success)
  41:              {
  42:                  do
  43:                  {
  44:                      string property = match.Groups["property"].Value;
  45:                      sb.AppendLine();
  46:   
  47:                      sb.AppendLine("public static string " + property);
  48:                      sb.AppendLine("{");
  49:                      sb.AppendLine("get");
  50:                      sb.AppendLine("{");
  51:                      sb.AppendLine("" + className + ".Culture = ResourceCulture;");
  52:                      sb.AppendLine("return " + className + "." + property + ";");
  53:                      sb.AppendLine("}");
  54:                      sb.AppendLine("}");
  55:   
  56:   
  57:                      match = match.NextMatch();
  58:                  } while (match.Success);
  59:              }
  60:   
  61:              sb.AppendLine("}");
  62:              sb.AppendLine("}");
  63:   
  64:   
  65:              using(StreamWriter wr = new StreamWriter(dirPath + @"" + fileName))
  66:              {
  67:                  wr.Write(sb.ToString());
  68:              }
  69:          }
  70:      }
  71:  #>

The <#+ on line 1 says to the code generator that a C# block of code will follow. The code in this block is standard C#.

**Something that I found to help a lot. Code as far as you can in a C# class and then move it to the .tt file. Intellisense and syntax highlighting is a big help.

Reference used: http://www.olegsych.com

Click here to download the template

Tags:

C# | T4

Powered by BlogEngine.NET 1.6.0.0
Theme by Mads Kristensen | Modified by Mooglegiant

About Me

Jacobus Meintjes
 
C# developer working with ASP.Net and/or Windows Forms.
Email Me

Cumulus

This will be shown to users with no Flash or Javascript.

Widget Twitter not found.

Root element is missing.X