Linee guida per la scrittura di modelli di testo T4

Queste linee guida generali possono essere utili se si genera codice programma o altre risorse dell'applicazione in Visual Studio. Non sono regole fisse.

Linee guida per i modelli T4 in fase di progettazione

I modelli T4 in fase di progettazione sono modelli che generano codice nel progetto di Visual Studio in fase di progettazione. Per altre informazioni, vedere Generazione di codice in fase di progettazione tramite modelli di testo T4.

Generare aspetti variabili dell'applicazione.

La generazione di codice è più utile per gli aspetti dell'applicazione che potrebbero cambiare durante il progetto o cambierà tra versioni diverse dell'applicazione. Separare questi aspetti delle variabili dagli aspetti più invarianti in modo da poter determinare più facilmente cosa deve essere generato. Ad esempio, se l'applicazione fornisce un sito Web, separare la pagina standard che gestisce le funzioni dalla logica che definisce i percorsi di spostamento da una pagina a un'altra.

Codificare gli aspetti delle variabili in uno o più modelli di origine.

Un modello è un file o un database letto da ogni modello per ottenere valori specifici per parti variabili del codice da generare. I modelli possono essere database, file XML di progettazione, diagrammi o linguaggi specifici del dominio. In genere, un modello viene usato per generare molti file in un progetto di Visual Studio. Ogni file viene generato da un modello separato.

È possibile usare più modelli in un progetto. Ad esempio, è possibile definire un modello per lo spostamento tra le pagine Web e un modello separato per il layout delle pagine.

Concentrarsi sul modello sulle esigenze e sul vocabolario degli utenti, non sull'implementazione.

Ad esempio, in un'applicazione di siti Web, si prevede che il modello faccia riferimento a pagine Web e collegamenti ipertestuali.

Idealmente, scegliere una forma di presentazione adatta al tipo di informazioni rappresentate dal modello. Ad esempio, un modello di percorsi di spostamento attraverso un sito Web può essere un diagramma di caselle e frecce.

Testare il codice generato.

Usare test manuali o automatizzati per verificare che il codice risultante funzioni come richiesto dagli utenti. Evitare di generare test dallo stesso modello da cui viene generato il codice.

In alcuni casi, i test generali possono essere eseguiti direttamente sul modello. Ad esempio, è possibile scrivere un test che garantisce che ogni pagina del sito Web possa essere raggiunta dalla navigazione da qualsiasi altra.

Consenti codice personalizzato: genera classi parziali.

Consentire il codice scritto a mano oltre al codice generato. È insolito che uno schema di generazione del codice sia in grado di tenere conto di tutte le possibili variazioni che potrebbero verificarsi. Di conseguenza, è consigliabile aggiungere o eseguire l'override di parte del codice generato. Quando il materiale generato si trova in un linguaggio .NET, ad esempio C# o Visual Basic, due strategie sono particolarmente utili:

  • Le classi generate devono essere parziali. In questo modo è possibile aggiungere contenuto al codice generato.

  • Le classi devono essere generate in coppie, una che eredita dall'altra. La classe base deve contenere tutti i metodi e le proprietà generati e la classe derivata deve contenere solo i costruttori. Ciò consente al codice scritto a mano di eseguire l'override di uno dei metodi generati.

In altri linguaggi generati, ad esempio XML, usare la <#@include#> direttiva per creare semplici combinazioni di contenuto scritto a mano e generato. In casi più complessi, potrebbe essere necessario scrivere un passaggio di post-elaborazione che combina il file generato con qualsiasi file scritto a mano.

Spostare materiale comune in file di inclusione o modelli di runtime.

Per evitare di ripetere blocchi simili di testo e codice in più modelli, usare la <#@ include #> direttiva . Per altre informazioni, vedere Direttiva di inclusione T4.

È anche possibile compilare modelli di testo in fase di esecuzione in un progetto separato e quindi chiamarli dal modello in fase di progettazione. A tale scopo, usare la <#@ assembly #> direttiva per accedere al progetto separato.

Prendere in considerazione lo spostamento di blocchi di codice di grandi dimensioni in un assembly separato.

Se sono presenti blocchi di codice di grandi dimensioni e blocchi di funzionalità di classe, potrebbe essere utile spostare parte di questo codice in metodi compilati in un progetto separato. È possibile usare la <#@ assembly #> direttiva per accedere al codice nel modello. Per altre informazioni, vedere Direttiva assembly T4.

È possibile inserire i metodi in una classe astratta che il modello può ereditare. La classe astratta deve ereditare da Microsoft.VisualStudio.TextTemplating.TextTransformation. Per altre informazioni, vedere Direttiva modello T4.

Generare codice, non file di configurazione.

Un metodo di scrittura di un'applicazione variabile consiste nel scrivere codice di programma generico che accetta un file di configurazione. Un'applicazione scritta in questo modo è molto flessibile e può essere riconfigurata quando i requisiti aziendali cambiano, senza ricompilare l'applicazione. Tuttavia, uno svantaggio di questo approccio è che l'applicazione avrà prestazioni meno buone rispetto a un'applicazione più specifica. Inoltre, il codice del programma sarà più difficile da leggere e gestire, in parte perché ha sempre a che fare con i tipi più generici.

Al contrario, un'applicazione le cui parti variabili vengono generate prima che la compilazione possa essere fortemente tipizzata. Ciò rende molto più semplice e affidabile scrivere codice scritto a mano e integrarlo con le parti generate del software.

Per ottenere il vantaggio completo della generazione del codice, provare a generare codice programma anziché file di configurazione.

Usare una cartella Codice generato.

Inserire i modelli e i file generati in una cartella di progetto denominata Codice generato, per chiarire che questi non sono file che devono essere modificati direttamente. Se si crea codice personalizzato per eseguire l'override o l'aggiunta alle classi generate, inserire tali classi in una cartella denominata Codice personalizzato. La struttura di un progetto tipico è simile alla seguente:

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

Linee guida per i modelli T4 in fase di esecuzione (pre-elaborati)

Spostare materiale comune in modelli ereditati.

È possibile usare l'ereditarietà per condividere metodi e blocchi di testo tra modelli di testo T4. Per altre informazioni, vedere Direttiva modello T4.

È anche possibile usare file di inclusione con modelli di runtime.

Spostare corpi di codice di grandi dimensioni in una classe parziale.

Ogni modello di runtime genera una definizione di classe parziale con lo stesso nome del modello. È possibile scrivere un file di codice contenente un'altra definizione parziale della stessa classe. È possibile aggiungere metodi, campi e costruttori alla classe in questo modo. Questi membri possono essere chiamati dai blocchi di codice nel modello.

Un vantaggio di questa operazione è che il codice è più facile da scrivere, perché IntelliSense è disponibile. È anche possibile ottenere una migliore separazione tra la presentazione e la logica sottostante.

Ad esempio, in MyReportText.tt:

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

In MyReportText-Methods.cs:

private string ComputeTotal() { ... }

Consenti codice personalizzato: specificare i punti di estensione.

Valutare la possibilità di generare metodi virtuali nei <blocchi di funzionalità della classe #>+. Ciò consente l'uso di un singolo modello in molti contesti senza modifiche. Anziché modificare il modello, è possibile costruire una classe derivata che fornisca la logica aggiuntiva minima. La classe derivata può essere un codice normale oppure può essere un modello di runtime.

Ad esempio, in MyStandardRunTimeTemplate.tt:

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

Nel codice di un'applicazione:

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

Linee guida per tutti i modelli T4

Separare la raccolta dati dalla generazione di testo.

Provare a evitare di combinare calcoli e blocchi di testo. In ogni modello di testo usare il primo <blocco di codice #> per impostare le variabili ed eseguire calcoli complessi. Dal primo blocco di testo fino alla fine del modello o del primo <blocco di funzionalità di classe #+ #>, evitare espressioni lunghe ed evitare cicli e condizionali, a meno che non contengano blocchi di testo. Questa procedura semplifica la lettura e la manutenzione del modello.

Non usare .tt per includere i file.

Usare un'estensione di file diversa, ad .ttinclude esempio per i file di inclusione. Usare .tt solo per i file che si desidera elaborare come modelli di testo in fase di esecuzione o in fase di progettazione. In alcuni casi, Visual Studio riconosce i .tt file e imposta automaticamente le relative proprietà per l'elaborazione.

Avviare ogni modello come prototipo fisso.

Scrivere un esempio di codice o testo da generare e assicurarsi che sia corretto. Modificare quindi l'estensione in .tt e inserire in modo incrementale il codice che modifica il contenuto leggendo il modello.

Prendere in considerazione l'uso di modelli tipizzati.

Sebbene sia possibile creare uno schema XML o di database per i modelli, potrebbe essere utile creare un linguaggio specifico del dominio (DSL). Un linguaggio DSL offre il vantaggio che genera una classe per rappresentare ogni nodo nello schema e le proprietà per rappresentare gli attributi. Ciò significa che è possibile programmare in termini di modello aziendale. Ad esempio:

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

Prendere in considerazione l'uso di diagrammi per i modelli.

Molti modelli sono presentati in modo più efficace e gestiti semplicemente come tabelle di testo, soprattutto se sono molto grandi.

Tuttavia, per alcuni tipi di requisiti aziendali, è importante chiarire set complessi di relazioni e flussi di lavoro e i diagrammi sono il mezzo più adatto. Un vantaggio di un diagramma è che è facile discutere con utenti e altri stakeholder. Generando codice da un modello a livello di requisiti aziendali, il codice è più flessibile quando cambiano i requisiti.

È anche possibile progettare un tipo di diagramma personalizzato come linguaggio specifico del dominio (DSL). Il codice può essere generato sia da UML che da DSL. Per altre informazioni, vedere Analisi e modellazione dell'architettura.