Condividi tramite


Blocchi di controllo del modello di testo T4

I blocchi di controllo consentono di scrivere codice nel modello di testo in modo da variare l'output. Esistono tre tipi di blocchi di controllo, contraddistinti dalle parentesi di apertura:

  • <# Standard control blocks #> possono contenere istruzioni.

  • <#= Expression control blocks #> possono contenere espressioni.

  • <#+ Class feature control blocks #> possono contenere metodi, campi e proprietà.

Blocco di controllo standard

I blocchi di controllo standard contengono istruzioni. Ad esempio, nel blocco standard seguente vengono ottenuti i nomi di tutti gli attributi nel documento XML:

<#@ assembly name="System.Xml.dll" #>
<#@ import namespace="System.Xml" #>

<#
    List<string> allAttributes = new List<string>();
    XmlDocument xDoc = new XmlDocument();
    xDoc.Load(@"E:\CSharp\Overview.xml");
    XmlAttributeCollection attributes = xDoc.Attributes;
    if (attributes.Count > 0)
    {
       foreach (XmlAttribute attr in attributes)
       {
           allAtributes.Add(attr.Name);
       }
     }  
#>

È possibile incorporare testo normale in un'istruzione composta quale if o for. Ad esempio, questo frammento genera una riga di output in ogni iterazione del ciclo:

<#
       foreach (XmlAttribute attr in attributes)
       {
#>
Found another one!
<#
           allAtributes.Add(attr.Name);
       }
#>
Nota di avvisoAttenzione

Utilizzare sempre {...} per delimitare istruzioni annidate contenenti testo normale incorporato. Il seguente esempio potrebbe non funzionare correttamente:

<# if (ShouldPrint) #> Some text. -- WRONG

È invece necessario includere le parentesi graffe{}, come riportato di seguito:

 
<#
 if (ShouldPrint)
 {   //  "{" REQUIRED
#>
Some text.
<#
 } 
#>

Blocco di controllo dell'espressione

I blocchi di controllo dell'espressione vengono utilizzati per codice che fornisce stringhe da scrivere nel file di output. Ad esempio, con l'esempio sopra illustrato, è possibile stampare i nomi degli attributi al file di output modificando il blocco di codice come segue:

<#
    XmlDocument xDoc = new XmlDocument();
    xDoc.Load(@"E:\CSharp\Overview.xml");
    XmlAttributeCollection attributes = xDoc.Attributes;
    if (attributes != null)
    {
       foreach (XmlAttribute attr in attributes)
       { 
#>
        <#= attr.Name #>
<#
       }
    }
#>

Blocco di controllo della funzionalità di classe

È possibile utilizzare blocchi di controllo della funzionalità di classe per aggiungere al modello di testo metodi, proprietà, campi o persino classi annidate. I blocchi della funzionalità di classe vengono utilizzati per lo più per fornire alle funzioni di supporto del codice in altre parti del modello di testo. Ad esempio, nel blocco della funzionalità di classe seguente viene scritta in maiuscolo la prima lettera del nome di attributo (se il nome contiene spazi vuoti, scrive in maiuscolo la prima lettera di ogni parola):

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

<#+
    private string FixAttributeName(string name)
    {
        return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(name);
    }
#>

Nota

Un blocco di controllo della funzionalità di classe non deve essere seguito dai blocchi di controllo standard nello stesso file modello. Tuttavia, questa restrizione non è applicabile al risultato dell'utilizzo delle direttive <#@include#>. Ogni file incluso può disporre di blocchi standard seguiti dai blocchi della funzionalità di classe.

È possibile creare una funzione che genera l'output incorporando il testo e i blocchi di espressione in un blocco di controllo della funzionalità di classe. Ad esempio:

<#+
    private string OutputFixedAttributeName(string name)
    {
#>
 Attribute:  <#= CultureInfo.CurrentCulture.TextInfo.ToTitleCase(name) #>
<#+  // <<< Notice that this is also a class feature block.
    }
#>

È possibile chiamare questa funzione da un blocco standard o da un altro blocco della funzionalità di classe:

<# foreach (Attribute attribute in item.Attributes)
{
  OutputFixedAttributeName(attribute.Name);
}
#>

Modalità di utilizzo dei blocchi di controllo

Tutto il codice in tutti i blocchi di controllo dell'espressione e standard in un unico modello (incluso tutto il codice nei modelli inclusi) è combinato per formare il metodo TransformText() del codice generato. Per ulteriori informazioni su come includere altri modelli di testo con la direttiva include, vedere Direttive di modello di testo T4.)

È necessario ricordare le considerazioni seguenti quando si utilizzano blocchi di controllo:

  • Lingua. In un modello di testo è possibile utilizzare codice C# o Visual Basic. La lingua predefinita è C#, ma è possibile specificare Visual Basic con il parametro language della direttiva template. Per ulteriori informazioni sulla direttiva template, vedere Direttive di modello di testo T4.

    Il linguaggio utilizzato nei blocchi di controllo non ha nulla a che vedere con il linguaggio o il formato del testo che si genera in un modello di testo. È possibile generare codice C# utilizzando codice Visual Basic o viceversa.

    È possibile utilizzare solo un linguaggio in un dato modello di testo, inclusi tutti i modelli di testo che si includono con la direttiva include.

  • Variabili locali. Poiché tutto il codice blocchi di controllo dell'espressione e standard in un modello di testo viene generato come un singolo metodo, è necessario assicurarsi che non vi siano conflitti tra i nomi delle variabili locali. Se si includono altri modelli di testo, è necessario assicurarsi che i nomi delle variabili sono univoci tra tutti i modelli inclusi. Un modo che garantirsi questa univocità consiste nell'aggiungere una stringa a ogni nome di variabile locale che identifichi il modello di testo nel quale è stato dichiarata.

    È anche una buona idea inizializzare le variabili locali a valori ragionevoli quando le si dichiara, in particolare quando si includono più modelli di testo.

  • Annidamento dei blocchi di controllo. I blocchi di controllo non possono essere annidati l'uno nell'altro. È necessario terminare sempre un dato blocco di controllo prima di aprirne un altro. Ad esempio, di seguito viene illustrato come stampare del testo in un blocco di espressione come parte di un blocco di controllo standard.

    <# 
    int x = 10;
    while (x-- > 0)
    {
    #>
    <#= x #>
    <# } #>
    
  • Refactoring. Per mantenere brevi e semplici i modelli di testo, si consiglia di evitare l'utilizzo di codice ripetitivo eseguendo il factoring del codice riutilizzabile in funzioni di supporto nei blocchi della funzionalità di classe o creando una propria classe del modello di testo che eredita dalla classe Microsoft.VisualStudio.TextTemplating.TextTransformation.