Freigeben über


Richtlinien für das Verfassen von T4-Textvorlagen

Diese allgemeinen Richtlinien können von Nutzen sein, wenn Sie Programmcode oder andere Anwendungsressourcen in Visual Studio generieren. Es handelt sich nicht um feste Regeln.

Richtlinien für T4-Entwurfszeitvorlagen

T4-Entwurfszeitvorlagen sind Vorlagen, die zur Entwurfszeit Code in Ihrem Visual Studio-Projekt generieren. Weitere Informationen finden Sie unter Generieren von Code zur Entwurfszeit mithilfe von T4-Textvorlagen.

Generieren Sie Code für variable Aspekte der Anwendung.

Die Codegenerierung ist vor allem für die Aspekte einer Anwendung nützlich, die sich während des Projekts oder zwischen verschiedenen Versionen der Anwendung ändern können. Trennen Sie diese variablen Aspekte von den unveränderlichen Aspekten, damit Sie leichter bestimmen können, was generiert werden muss. Wenn Ihre Anwendung beispielsweise eine Website bereitstellt, sollten Sie die Standardfunktionen für die Seitenbereitstellung von der Logik trennen, die die Navigationspfade von einer Seite zur anderen definiert.

Codieren Sie die variablen Aspekte in einem oder mehreren Quellmodellen.

Ein Modell ist eine Datei oder eine Datenbank, die jede Vorlage liest, um bestimmte Werte für variable Teile des zu generierenden Codes abzurufen. Modelle können Datenbanken, selbst erstellte XML-Dateien, Diagramme oder domänenspezifische Sprachen sein. Üblicherweise wird ein Modell verwendet, um viele Dateien in einem Visual Studio-Projekt zu generieren. Jede Datei wird aus einer separaten Vorlage generiert.

Sie können mehr als ein Modell in einem Projekt verwenden. Beispielsweise können Sie ein Modell für die Navigation zwischen Webseiten und ein separates Modell für das Layout der Seiten definieren.

Richten Sie das Modell auf die Bedürfnisse und das Vokabular der Benutzer aus, nicht auf Ihre Implementierung.

Bei einer Websiteanwendung zum Beispiel ist zu erwarten, dass sich das Modell auf Webseiten und Hyperlinks bezieht.

Idealerweise wählen Sie eine Präsentationsform, die zu der Art von Informationen passt, die das Modell repräsentiert. Ein Modell der Navigationspfade durch eine Website könnte zum Beispiel ein Diagramm aus Kästchen und Pfeilen sein.

Testen Sie den generierten Code.

Überprüfen Sie mithilfe manueller oder automatisierter Tests, ob der resultierende Code so wie vom Benutzer gefordert funktioniert. Vermeiden Sie es, Tests anhand desselben Modells zu erstellen, mit dem auch der Code generiert wird.

In einigen Fällen können allgemeine Tests direkt am Modell durchgeführt werden. Sie könnten zum Beispiel einen Test schreiben, der sicherstellt, dass jede Seite der Website per Navigation von jeder anderen Seite aus erreicht werden kann.

Lassen Sie benutzerdefinierten Code zu: Generieren Sie partielle Klassen.

Lassen Sie zusätzlich zum generierten Code auch selbstgeschriebenen Code zu. Normalerweise kann ein Schema zur Codegenerierung nicht alle denkbaren Variationen berücksichtigen, die auftreten können. Deshalb sollten Sie damit rechnen, dass Sie Teile des generierten Codes ergänzen oder überschreiben müssen. Wenn das generierte Material in einer .NET-Sprache wie C# oder Visual Basic vorliegt, sind zwei Strategien besonders hilfreich:

  • Die generierten Klassen sollten partielle Klassen sein. So können Sie dem generierten Code Inhalte hinzufügen.

  • Klassen sollten paarweise generiert werden, wobei eine Klasse von der anderen erbt. Die Basisklasse sollte alle generierten Methoden und Eigenschaften enthalten, während die abgeleitete Klasse nur die Konstruktoren enthalten sollte. Dadurch kann Ihr selbstgeschriebener Code jede der generierten Methoden überschreiben.

In anderen generierten Sprachen wie z. B. XML verwenden Sie die Anweisung <#@include#>, um einfache Kombinationen aus selbstgeschriebenen und generierten Inhalten zu erstellen. In komplexeren Fällen müssen Sie möglicherweise einen Nachbearbeitungsschritt schreiben, der die generierte Datei mit allen selbst geschriebenen Dateien kombiniert.

Verschieben Sie allgemeines Material in Includedateien oder Laufzeitvorlagen.

Um die Wiederholung ähnlicher Text- und Codeblöcke in den verschiedenen Vorlagen zu vermeiden, verwenden Sie die Anweisung <#@ include #>. Weitere Information finden Sie unter T4-Anweisung „include“.

Es ist auch möglich, Laufzeittextvorlagen in einem separaten Projekt zu erstellen und diese dann von der Entwurfszeitvorlage aus aufzurufen. Verwenden Sie dazu die Anweisung <#@ assembly #>, um auf das separate Projekt zuzugreifen.

Erwägen Sie das Verschieben großer Codeblöcke in eine separate Assembly.

Wenn Sie über große Codeblöcke und Klassenfunktionsblöcke verfügen, kann es sinnvoll sein, einen Teil dieses Codes in Methoden zu verschieben, die Sie in einem separaten Projekt kompilieren. Sie können die Anweisung <#@ assembly #> verwenden, um auf den Code in der Vorlage zuzugreifen. Weitere Informationen finden Sie unter T4-Anweisung „assembly“.

Sie können die Methoden in eine abstrakte Klasse aufnehmen, die die Vorlage erben kann. Die abstrakte Klasse muss von Microsoft.VisualStudio.TextTemplating.TextTransformation erben. Weitere Information finden Sie unter T4-Anweisung „template“.

Generieren Sie Code, keine Konfigurationsdateien.

Eine Methode zum Schreiben einer variablen Anwendung besteht darin, generischen Programmcode zu schreiben, der eine Konfigurationsdatei akzeptiert. Eine auf diese Weise geschriebene Anwendung ist sehr flexibel und kann bei geänderten Geschäftsanforderungen neu konfiguriert werden, ohne dass die Anwendung neu erstellt werden muss. Ein Nachteil dieses Ansatzes ist jedoch, dass die Anwendung eine geringere Leistung bietet als eine spezifischere Anwendung. Außerdem ist der Programmcode schwieriger zu lesen und zu pflegen, unter anderem deshalb, weil stets mit den allgemeinsten Typen gearbeitet werden muss.

Im Gegensatz dazu kann eine Anwendung, deren variable Teile vor der Kompilierung generiert werden, stark typisiert sein. Dies macht es wesentlich einfacher und zuverlässiger, selbstgeschriebenen Code in die generierten Teile der Software zu integrieren.

Um die Vorteile der Codegenerierung voll auszuschöpfen, sollten Sie versuchen, Programmcode anstelle von Konfigurationsdateien zu generieren.

Verwenden Sie einen Ordner für generierten Code.

Platzieren Sie die Vorlagen und die generierten Dateien in einem Projektordner mit dem Namen Generated Code, um deutlich zu machen, dass diese Dateien nicht direkt bearbeitet werden sollten. Wenn Sie benutzerdefinierten Code erstellen, um die generierten Klassen zu überschreiben oder zu ergänzen, platzieren Sie diese Klassen in einem Ordner mit dem Namen Custom Code. Die Struktur eines typischen Projekts sieht folgendermaßen aus:

MyProject
   Custom Code
      Class1.cs
      Class2.cs
   Generated Code
      Class1.tt
          Class1.cs
      Class2.tt
          Class2.cs
   AnotherClass.cs

Richtlinien für (vorverarbeitete) T4-Laufzeitvorlagen

Verschieben Sie allgemeines Material in geerbte Vorlagen.

Mithilfe der Vererbung können Sie Methoden und Textblöcke zwischen T4-Textvorlagen gemeinsam nutzen. Weitere Information finden Sie unter T4-Anweisung „template“.

Sie können auch Includedateien verwenden, die Laufzeitvorlagen enthalten.

Verschieben Sie große Codeabschnitte in eine partielle Klasse.

Jede Laufzeitvorlage generiert eine partielle Klassendefinition, die den gleichen Namen aufweist wie die Vorlage. Sie können eine Codedatei schreiben, die eine weitere partielle Definition der gleichen Klasse enthält. Auf diese Weise können Sie der Klasse Methoden, Felder und Konstruktoren hinzufügen. Diese Member können über die Codeblöcke in der Vorlage aufgerufen werden.

Ein Vorteil dieser Vorgehensweise ist, dass der Code einfacher zu schreiben ist, da IntelliSense zur Verfügung steht. Außerdem erreichen Sie eine bessere Trennung zwischen der Präsentation und der zugrunde liegenden Logik.

Beispiel: MyReportText.tt:

The total is: <#= ComputeTotal() #>

In MyReportText-Methods.cs:

private string ComputeTotal() { ... }

Lassen Sie benutzerdefinierten Code zu: Geben Sie Erweiterungspunkte an.

Erwägen Sie das Generieren virtueller Methoden in <#+ Klassenfunktionsblöcken #>. Dadurch kann eine einzige Vorlage ohne Änderung in zahlreichen Kontexten genutzt werden. Anstatt die Vorlage zu ändern, können Sie eine abgeleitete Klasse erstellen, die das Minimum an zusätzlicher Logik liefert. Bei der abgeleiteten Klasse kann es sich entweder um regulären Code oder um eine Laufzeitvorlage handeln.

Beispiel: „MyStandardRunTimeTemplate.tt“:

This page is copyright <#= CompanyName() #>.
<#+ protected virtual string CompanyName() { return ""; } #>

Im Code einer Anwendung:

class FabrikamTemplate : MyStandardRunTimeTemplate
{
  protected override string CompanyName() { return "Fabrikam"; }
}
...
  string PageToDisplay = new FabrikamTemplate().TextTransform();

Richtlinien für alle T4-Vorlagen

Trennen Sie die Datensammlung von der Textgenerierung.

Vermeiden Sie die Vermischung von Berechnungs- und Textblöcken. Verwenden Sie in jeder Textvorlage den ersten <# Codeblock #>, um Variablen festzulegen und komplexe Berechnungen durchzuführen. Vermeiden Sie vom ersten Textblock bis zum Ende der Vorlage oder dem ersten <#+ Klassenfunktionsblock #> lange Ausdrücke sowie Schleifen und Bedingungen, soweit sie keine Textblöcke enthalten. Dadurch ist die Vorlage einfacher zu lesen und zu pflegen.

Verwenden Sie .tt nicht für Includedateien.

Verwenden Sie für Includedateien eine andere Dateinamenerweiterung, z. B. .ttinclude. Verwenden Sie .tt nur für Dateien, die entweder als Laufzeit- oder als Entwurfszeittextvorlagen verarbeitet werden sollen. In einigen Fällen erkennt Visual Studio .tt-Dateien und legt ihre Eigenschaften automatisch für die Verarbeitung fest.

Starten Sie jede Vorlage als festen Prototyp.

Schreiben Sie ein Beispiel für den zu generierenden Code oder Text, und stellen Sie sicher, dass er korrekt ist. Ändern Sie dann die Erweiterung in „.tt“, und fügen Sie nach und nach Code ein, der den Inhalt durch Lesen des Modells ändert.

Erwägen Sie die Verwendung von typisierten Modellen.

Sie können zwar ein XML- oder Datenbankschema für Ihre Modelle erstellen, aber es kann auch sinnvoll sein, eine domänenspezifische Sprache (DSL) zu erstellen. Eine DSL hat den Vorteil, dass sie eine Klasse generiert, die jeden Knoten im Schema repräsentiert, und Eigenschaften, die die Attribute darstellen. Das bedeutet, dass Sie entsprechend dem Geschäftsmodell programmieren können. Zum Beispiel:

Team Members:
<# foreach (Person p in team.Members)
 { #>
    <#= p.Name #>
<# } #>

Erwägen Sie die Verwendung von Diagrammen für Ihre Modelle.

Viele Modelle lassen sich am effizientesten in Form von Texttabellen darstellen und verwalten, insbesondere wenn sie sehr groß sind.

Für einige Arten von Geschäftsanforderungen ist es jedoch wichtig, komplexe Beziehungen und Arbeitsabläufe zu verdeutlichen, und dafür sind Diagramme am besten geeignet. Der Vorteil eines Diagramms liegt darin, dass es problemlos mit Benutzern und anderen Projektbeteiligten besprochen werden kann. Wenn Sie auf Ebene der Geschäftsanforderungen Code aus einem Modell generieren, können Sie Ihren Code flexibler gestalten, wenn sich die Anforderungen ändern.

Sie können auch einen eigenen Diagrammtyp in Form einer domänenspezifischen Sprache (DSL) entwerfen. Code kann sowohl aus UML als auch aus DSLs generiert werden. Weitere Informationen finden Sie unter Analysieren und Modellieren der Architektur.