Share via


Schreiben einer T4-Textvorlage

Eine Textvorlage enthält den Text, der aus ihr generiert wird. Eine Vorlage, die eine Webseite erstellt, enthält beispielsweise „<html>...“ und alle anderen Standardteile einer HTML-Seite. In die Vorlage sind Kontrollblöcke eingefügt, bei denen es sich um Fragmente des Programmcodes handelt. Kontrollblöcke stellen veränderliche Werte bereit und ermöglichen es, Bedingungen für Teile des Texts zu definieren und Teile des Texts zu wiederholen.

Diese Struktur vereinfacht das Entwickeln einer Vorlage, da Sie mit einem Prototyp der generierten Datei beginnen und nach und nach Kontrollblöcke zum Verändern des Ergebnisses einfügen können.

Textvorlagen bestehen aus den folgenden Teilen:

  • Anweisungen: Elemente, die steuern, wie die Vorlage verarbeitet wird.

  • Textblöcke: Der Inhalt, der direkt in die Ausgabe kopiert wird.

  • Kontrollblöcke: Programmcode, durch den Variablenwerte in den Text eingefügt und bedingte oder wiederholte Teile des Texts gesteuert werden.

Wenn Sie die Beispiele in diesem Artikel testen möchten, kopieren Sie sie wie in Generieren von Code zur Entwurfszeit mithilfe von T4-Textvorlagen beschrieben in eine Vorlagendatei. Speichern Sie Vorlagendatei nach dem Bearbeiten, und überprüfen Sie dann die .txt-Ausgabedatei.

Anweisungen

Textvorlagenanweisungen stellen allgemeine Anweisungen zum Generieren des Transformationscodes und der Ausgabedatei für die Textvorlagen-Engine bereit.

Die folgende Anweisung gibt z. B. an, dass die Ausgabedatei die Erweiterung .txt haben soll:

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

Weitere Informationen zu Anweisungen finden Sie unter T4-Textvorlagenanweisungen.

Textblöcke

Durch einen Textblock wird Text direkt in die Ausgabedatei eingefügt. Für Textblöcke wird keine spezielle Formatierung verwendet. Die folgende Textvorlage erzeugt z. B. eine Textdatei, die das Wort "Hello" enthält:

<#@ output extension=".txt" #>
Hello

Kontrollblöcke

Kontrollblöcke sind Abschnitte des Programmcodes, die zum Transformieren der Vorlagen verwendet werden. Die Standardsprache ist C#, zur Verwendung von Visual Basic können Sie jedoch die folgende Anweisung am Anfang der Datei schreiben:

<#@ template language="VB" #>

Die Sprache, in der Sie den Code in den Kontrollblöcken schreiben, steht in keinem Zusammenhang mit der Sprache des generierten Texts.

Standardkontrollblöcke

Ein Standardkontrollblock ist ein Abschnitt des Programmcodes, durch den ein Teil der Ausgabedatei generiert wird.

Sie können in einer Vorlagendatei eine beliebige Anzahl von Textblöcken und Standardkontrollblöcken kombinieren. Es ist jedoch nicht möglich, einen Kontrollblock in einen anderen Kontrollblock einzufügen. Jeder Standardkontrollblock ist durch die Symbole <# ... #> begrenzt.

Beim folgenden Kontrollblock und Textblock wird z. B. die Zeile "0, 1, 2, 3, 4 Hello!" in die Ausgabedatei eingefügt:

<#
    for(int i = 0; i < 4; i++)
    {
        Write(i + ", ");
    }
    Write("4");
#> Hello!

Anstatt explizite Write()-Anweisungen zu verwenden, können Sie Text und Code verschachteln. Im folgenden Beispiel wird "Hello!" viermal gedruckt:

<#
    for(int i = 0; i < 4; i++)
    {
#>
Hello!
<#
    }
#>

Sie können überall dort einen Textblock einfügen, wo eine Write();-Anweisung im Code zulässig wäre.

Hinweis

Wenn Sie einen Textblock innerhalb einer Verbundanweisung einbetten, z. B. in einer Schleife oder Bedingung, muss der Textblock immer in geschweifte Klammern {...} gesetzt werden.

Ausdruckskontrollblöcke

Durch einen Ausdruckskontrollblock wird ein Ausdruck ausgewertet und in eine Zeichenfolge konvertiert. Diese Zeichenfolge wird in die Ausgabedatei eingefügt.

Ausdruckskontrollblöcke sind durch die Symbole <#= ... #> begrenzt.

Beim folgenden Kontrollblock enthält die Ausgabedatei z. B. "5":

<#= 2 + 3 #>

Beachten Sie, dass das öffnende Symbol aus drei Zeichen besteht „<#=“.

Der Ausdruck kann beliebige gültige Variablen enthalten. Durch den folgenden Block werden z. B. Zeilen mit Zahlen ausgegeben:

<#@ output extension=".txt" #>
<#
    for(int i = 0; i < 4; i++)
    {
#>
This is hello number <#= i+1 #>: Hello!
<#
    }
#>

Klassenfunktionskontrollblöcke

Ein Klassenfunktionskontrollblock definiert Eigenschaften, Methoden oder anderen Code, die nicht in der Haupttransformation enthalten sein sollten. Klassenfunktionsblöcke werden häufig für Hilfsfunktionen verwendet. Normalerweise werden Klassenfunktionsblöcke in separaten Dateien gespeichert, damit sie in mehrere Textvorlagen eingeschlossen werden können.

Klassenfunktionskontrollblöcke sind durch die Symbole <#+ ... #> begrenzt.

In der folgenden Vorlagendatei wird z. B. eine Methode deklariert und verwendet:

<#@ output extension=".txt" #>
Squares:
<#
    for(int i = 0; i < 4; i++)
    {
#>
    The square of <#= i #> is <#= Square(i+1) #>.
<#
    }
#>
That is the end of the list.
<#+   // Start of class feature block
private int Square(int i)
{
    return i*i;
}
#>

Klassenfunktionen müssen am Ende der Datei eingefügt werden, in der sie geschrieben werden. <#@include#> kann jedoch auch dann für eine Datei, die eine Klassenfunktion enthält, verwendet werden, wenn nach der include-Direktive Standardblöcke und Text eingefügt werden.

Weitere Informationen zu Kontrollblöcken finden Sie unter Kontrollblöcke für Textvorlagen.

Klassenfunktionsblöcke können Textblöcke enthalten

Sie können eine Methode schreiben, durch die Text generiert wird. Beispiel:

List of Squares:
<#
   for(int i = 0; i < 4; i++)
   {  WriteSquareLine(i); }
#>
End of list.
<#+   // Class feature block
private void WriteSquareLine(int i)
{
#>
   The square of <#= i #> is <#= i*i #>.
<#+
}
#>

Es ist sinnvoll, Methoden zum Generieren von Text in einer separaten Datei zu speichern, die in mehrere Vorlagen eingeschlossen werden kann.

Verwenden von externen Definitionen

Assemblys

In den Codeblöcken der Vorlage können Typen verwendet werden, die in den am häufigsten verwendeten .NET-Assemblys definiert sind, z. B. System.dll. Außerdem können Sie auf andere .NET-Assemblys oder eigene Assemblys verweisen. Sie können einen Pfadnamen oder den starken Namen einer Assembly angeben:

<#@ assembly name="System.Xml" #>

Verwenden Sie absolute Pfadnamen oder standardmäßige Makronamen im Pfadnamen. Beispiel:

<#@ assembly name="$(SolutionDir)library\MyAssembly.dll" #>

Die assembly-Anweisung hat in einer vorverarbeiteten Textvorlage keinerlei Auswirkungen.

Weitere Informationen finden Sie unter T4-Anweisung „assembly“.

Namespaces

Die import-Anweisung entspricht der using-Klausel in C# bzw. der imports-Klausel in Visual Basic. Sie ermöglicht es Ihnen, ohne einen vollqualifizierten Namen auf Typen im Code zu verweisen:

<#@ import namespace="System.Xml" #>

Sie können beliebig viele assembly- und import-Direktiven verwenden. Diese Direktiven müssen vor Text- und Kontrollblöcken eingefügt werden.

Weitere Information finden Sie unter T4-Anweisung „import“.

Einschließen von Code und Text

Die include-Anweisung fügt Text aus einer anderen Vorlagendatei ein. Die folgende Direktive fügt z. B. den Inhalt von test.txt ein.

<#@ include file="c:\test.txt" #>

Der eingeschlossene Inhalt wird fast so verarbeitet, als wäre er Teil der jeweiligen Textvorlage. Sie können jedoch auch dann eine Datei einschließen, die einen Klassenfunktionsblock <#+...#> enthält, wenn nach der include-Direktive normale Text- und Standardkontrollblöcke eingefügt werden.

Weitere Information finden Sie unter T4-Anweisung „include“.

Hilfsmethoden

Mehrere Methoden wie z. B. Write() stehen Ihnen in einem Kontrollblock immer zur Verfügung. Dazu zählen Methoden zum Einziehen der Ausgabe und Melden von Fehlern.

Sie können auch einen eigenen Satz von Hilfsmethoden schreiben.

Weitere Informationen finden Sie unter Hilfsprogrammmethoden für Textvorlagen.

Transformieren von Daten und Modellen

Einer der sinnvollsten Verwendungszwecke von Textvorlagen ist das Generieren von Material basierend auf dem Inhalt einer Quelle, z. B. einem Modell, einer Datenbank oder einer Datendatei. Die Vorlage extrahiert Daten und formatiert sie neu. Durch eine Auflistung von Vorlagen kann eine solche Quelle in mehrere Dateien transformiert werden.

Zum Lesen der Quelldatei sind mehrere Ansätze verfügbar.

Lesen Sie eine Datei in der Textvorlage. Dies ist einfachste Methode, um Daten in die Vorlage abzurufen:

<#@ import namespace="System.IO" #>
<# string fileContent = File.ReadAllText(@"C:\myData.txt"); ...

Laden Sie eine Datei als navigierbares Modell. Eine effektivere Methode besteht darin, die Daten als ein Modell zu lesen, durch das der Textvorlagencode navigieren kann. Sie können z. B. eine XML-Datei laden und mit XPath-Ausdrücken darin navigieren. Sie können auch mithilfe von xsd.exe eine Gruppe von Klassen erstellen, mit denen die XML-Daten gelesen werden können.

Bearbeiten Sie die Modelldatei in einem Diagramm oder Formular. Mit DSL-Tools können Sie ein Modell als Diagramm oder Windows-Formular bearbeiten. Dadurch kann das Modell einfacher mit Benutzern der generierten Anwendung besprochen werden. Die DSL-Tools erstellen auch eine Gruppe stark typisierter Klassen, die die Struktur des Modells wiedergeben. Weitere Informationen finden Sie unter Generieren von Code für eine domänenspezifische Sprache.

Relative Dateipfade in den Entwurfszeitvorlagen

Wenn Sie in einer Entwurfszeittextvorlage auf eine Datei in einem Speicherort verweisen möchten, der relativ zur Textvorlage ist, verwenden Sie this.Host.ResolvePath(). Sie müssen auch hostspecific="true" in der template-Anweisung festlegen:

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ import namespace="System.IO" #>
<#
 // Find a path within the same project as the text template:
 string myFile = File.ReadAllText(this.Host.ResolvePath("MyFile.txt"));
#>
Content of MyFile.txt is:
<#= myFile #>

Sie können auch andere Dienste empfangen, die vom Host bereitgestellt werden. Weitere Informationen finden Sie unter Zugreifen auf Visual Studio oder andere Hosts von einer T4-Textvorlage.

Entwurfszeittextvorlagen werden in einer separaten AppDomain ausgeführt

Eine Entwurfszeittextvorlage wird in einer AppDomain ausgeführt, die von der Hauptanwendung getrennt ist. In den meisten Fällen ist dies nicht wichtig, doch in bestimmten komplexen Fällen können sich Einschränkungen ergeben. Wenn Sie z. B. Daten in oder aus der Vorlage von einem separaten Dienst übergeben möchten, muss der Dienst eine serialisierbare API bereitstellen.

(Dies gilt nicht für eine Laufzeittextvorlage, in der Code bereitgestellt wird, der zusammen mit dem restlichen Code kompiliert wird.)

Bearbeiten von Vorlagen

Spezialisierte Textvorlagen-Editoren können aus dem Onlinekatalog des Erweiterungs-Managers heruntergeladen werden. Klicken Sie im Menü Extras auf Erweiterungs-Manager. Klicken Sie auf Onlinekatalog, und verwenden Sie dann das Suchtool.