Using extension methods in T4 templates

Adam has a groovy post on T4, but he's under the impression that you can't use C# extension methods in T4. I just wanted to discuss the limitations that exist and show how you can take advantage of this cool C#/VB 3.5 feature.

Extension methods require you to declare a top-level static class, and don't support nested class scope.

With T4, it's necessary to create a class feature block <#+ #> if you want to declare another class directly in your template and class feature blocks translate this into a nested class.

This means you can't use the really obvious syntax of

    1: <#@ template language="C#v3.5" debug="true" #>
    2: <#@ import namespace="System.Collections.Generic" #>
    3: <#
    4: List<string> strings = new List<string>();
    5: strings.Add("Foo");
    6: strings.Add("Bar");
    7: foreach ( string item in strings)
    8: {
    9: #>
   10: This is a test of <#= item.Wooga() #>
   11: <#
   12: }
   13: #>
   14:  
   15: <#+
   16:     public static class WoogaHelper
   17:     {
   18:         public static string Wooga(this string input)
   19:         {
   20:             return "Wooga" + input;
   21:         }
   22:     }
   23: #>
   24:  
   25:  

BTW, note that I've set language="C#v3.5" in my template directive to switch T4 to use the latest compiler.

However, to get things to work, we need to move our WoogaHelper class into a separate assembly and import that into T4; then all is sunny and happy in the world.

In a library assembly building to produce ExtMethods.dll:

    1: using System;
    2: using System.Collections.Generic;
    3: using System.Linq;
    4: using System.Text;
    5:  
    6: namespace Extmethods
    7: {
    8:     public static class WoogaHelper
    9:     {
   10:         public static string Wooga(this string input)
   11:         {
   12:             return "Wooga" + input;
   13:         }
   14:     }
   15: }

Then add a reference to the ExtMethods assembly (either as an assembly or project reference) to the project that contains your T4 template and add an assembly and import directive to your template, like so:

    1: <#@ template language="C#v3.5" debug="true" #>
    2: <#@ import namespace="System.Collections.Generic" #>
    3: <#@ import namespace="Extmethods" #>
    4: <#@ assembly name="Extmethods.dll" #>
    5: <#
    6: List<string> strings = new List<string>();
    7: strings.Add("Foo");
    8: strings.Add("Bar");
    9: foreach ( string item in strings)
   10: {
   11: #>
   12: This is a test of <#= item.Wooga() #>
   13: <#
   14: }
   15: #>
   16:  

 

Extension methods can be particularly helpful within T4, as you often want to do some obscure code spit based on a type that would make no sense given an item of that type in any other context. Enjoy.

 

Technorati Tags: T4,VSX,Visual Studio