T4 und Generierung multipler Dateien

26. September 2013

Wie das Text Templating Transformation Toolkit (T4) verwendet wird, habe ich bereits im Beitrag “Code Coverage bei generiertem Code mit T4 korrigieren” im Abschnitt “T4 im Einsatz” beschrieben. Dabei wird eine einzelne Ausgabedatei generiert, was in den meisten Anwendungsfällen auch gewollt ist.

Gelegentlich kann es aber sinnvoll sein, mehrere separate Dateien zu generieren, z. B. um beim Debuggen nicht in einer Datei mit unzähligen Klassen navigieren zu müssen oder um die Klassenstruktur im Projekt granularer abzubilden.

In diesem Artikel zeige ich, wie man mit T4 multiple Dateien generieren kann.

T4MultiFile

Ist das erklärte Ziel mehrere separate Dateien iterativ durch Verwendung einer gemeinsamen Logik und des T4-Toolkits zu generieren, dann kann T4MultiFile eine Hilfe sein.

T4MultiFile ist eine T4 Skript-Vorlage, die unter http://www.nuget.org/packages/T4MultiFile/ zu finden ist, und in Visual Studio 2012 sehr einfach mit der NuGet-Konsole integrierbar ist. Dafür reicht der NuGet-Konsolenbefehl:

PM> Install-Package T4MultiFile

Der Projektmappe werden damit folgende Dateien hinzugefügt:

  • MultipleOutputHelper.ttinclude
  • MultipleSample.tt

MultipleOutputHelper.ttinclude

Die ttinclude-Datei sollte nicht verändert, sondern in der Vorlage referenziert werden. Sie beinhaltet den Manager für die Generierung neuer Seiten.

// Manager mit den statischen Instanzen Host und GenerationEnvironment    

var manager = Manager.Create(Host, GenerationEnvironment);

 

manager.StartNewFile(fileName); // neue Datei    

 

//    

// Dateiinhalt    

//    

 

manager.EndBlock(); // Dateiende

MultipleSample.tt

Die “MultipleSample.tt” ist eine Beispieldatei. Sie soll die Verwendung der ttinclude-Datei und des beinhalteten Managers aufzeigen. Leider hat die Version 0.1 einen Bug. Zum Korrigieren ist das schließende T4-Element “#>” an folgende Zeile der Vorlage anzuhängen:

<# var manager = Manager.Create(Host, GenerationEnvironment);

Das Resultat sieht dann so aus:

<# var manager = Manager.Create(Host, GenerationEnvironment); #>

Mit dem Speichern werden die Dateien “MultiSample.xsl” und “MultipleTest.generated.cs” generiert.

Die Generierung der Datei “MultipleSample.xsl” ist optional. Um das Generieren zu unterbinden, ist die output-Direktive der Vorlage zu löschen:

<#@ output extension=".xsl"#>

Alternativ lässt sich diese output-Ausgabe für das Mitloggen von Generierungsereignissen oder des Zeitpunkts der letzten Ausführung des Skriptes verwenden. Dafür muss nur beachtet werden, dass Inhalte, die in der output-Datei erscheinen sollen, vor manager.StartNewFile(…) oder nach manager.EndBlock() als Ausgabe definiert werden.

Beispiel

Der folgende Code beinhaltet den gesamten Inhalt einer Beispiel-Vorlage. In einer for-Schleife werden iterativ Klassen generiert, daneben noch die .log.txt, die den Startpunkt, Endpunkt und die erstellten Dateien loggt.

<#@ template debug="True" language="C#" hostspecific="True" #>    

<#@ output extension=".generated.log.txt"#>    

<#@ include file="MultipleOutputHelper.ttinclude" #>    

<#  bool doMultiFile=true;    

#>

<# var manager = Manager.Create(Host, GenerationEnvironment); #>


Generation started: <#= DateTime.Now.ToString()#>

 

<# for(int i=1; i < 20; i++)    

{

    string fileName = LastFileName = "MultipleTest" + i.ToString() + ".generated.cs";   

    manager.StartNewFile(fileName); 

#>

namespace T4Enumerator    

{

    public class MultipleTest<#= i.ToString()#>    

    {

    }

}

<# 

manager.EndBlock();

 

#>

File Generated: <#= LastFileName #>

<#

}

manager.Process(doMultiFile); #>

 

Generation ended: <#= DateTime.Now.ToString()#>

 

<#+ string LastFileName = ""; // globale Variable zur Ausgabe im Log#>    

Hier die generierte Ausgabe der .log.txt:

Generation started: 25.07.2013 14:55:25

File Generated: MultipleTest1.generated.cs
File Generated: MultipleTest2.generated.cs
File Generated: MultipleTest3.generated.cs

File Generated: MultipleTest19.generated.cs

Generation ended: 25.07.2013 14:55:27

Fazit

Mit T4MultiFile hat man eine T4 Skript-Vorlage, die einfach einzubinden und zu verwenden ist und die es ermöglicht multiple Ausgabedateien mit einem T4-Skript zu generieren.

Die notwendigen Schritte dafür sind:

  • Importieren der Vorlage z. B. mittels NuGet
  • Umbenennen der MultiSample.tt in einen projektbezogenen, sprechenden Namen
  • output-Direktive evtl. neu definieren oder entfernen
  • Jede neue Datei mit manager.StartNewFile(…) starten und mit manager.EndBlock() beenden
  • Logik der Dateiinhalte implementieren