Generación de texto en tiempo de ejecución con plantillas de texto T4Run-Time Text Generation with T4 Text Templates

Puede generar cadenas de texto en la aplicación en tiempo de ejecución mediante plantillas de texto en tiempo de ejecución de Visual Studio.You can generate text strings in your application at run time by using Visual Studio runtime text templates. No es necesario que el equipo en el que se ejecuta la aplicación tenga Visual Studio.The computer where the application executes does not have to have Visual Studio. Las plantillas en tiempo de ejecución a veces se denominan "plantillas de texto preprocesadas" porque, en tiempo de compilación, la plantilla genera código que se ejecuta en tiempo de ejecución.Runtime templates are sometimes called "preprocessed text templates" because at compile time, the template generates code that is executed at run time.

Cada plantilla es una combinación del texto tal como aparecerá en la cadena generada y fragmentos de código de programa.Each template is a mixture of the text as it will appear in the generated string, and fragments of program code. Los fragmentos del programa suministran valores para las partes variables de la cadena y controlan también las partes condicionales y repetidas.The program fragments supply values for the variable parts of the string, and also control conditional and repeated parts.

Por ejemplo, la siguiente plantilla podría usarse en una aplicación que crea un informe HTML.For example, the following template could be used in an application that creates an HTML report.

<#@ template language="C#" #>
<html><body>
<h1>Sales for Previous Month</h2>
<table>
    <# for (int i = 1; i <= 10; i++)
       { #>
         <tr><td>Test name <#= i #> </td>
             <td>Test value <#= i * i #> </td> </tr>
    <# } #>
 </table>
This report is Company Confidential.
</body></html>

Observe que la plantilla es una página HTML en la que las partes variables se han reemplazado por código de programa.Notice that the template is an HTML page in which the variable parts have been replaced with program code. Puede comenzar el diseño de dicha página escribiendo un prototipo estático de la página HTML.You could begin the design of such a page by writing a static prototype of the HTML page. A continuación, podría reemplazar la tabla y otras partes variables por el código de programa que genera el contenido que varía de una ocasión a la siguiente.You could then replace the table and other variable parts with program code that generates the content that varies from one occasion to the next.

El uso de una plantilla en la aplicación facilita la visualización de la forma final de la salida, por ejemplo, una larga serie de instrucciones Write.Using a template in your application makes it is easier to see the final form of the output than you could in, for example, a long series of write statements. Realizar cambios en el formato de la salida es más fácil y confiable.Making changes to the form of the output is easier and more reliable.

Crear una plantilla de texto en tiempo de ejecución en cualquier aplicaciónCreating a Run-Time Text Template in any Application

Para crear una plantilla de texto en tiempo de ejecuciónTo create a run-time text template

  1. En Explorador de soluciones, en el menú contextual del proyecto, elija agregar > nuevo elemento.In Solution Explorer, on the shortcut menu of your project, choose Add > New Item.

  2. En el cuadro de diálogo Agregar nuevo elemento , seleccione plantilla de texto en tiempo de ejecución.In the Add New Item dialog box, select Runtime Text Template. (En Visual Basic mire en elementos comunes > General).(In Visual Basic look under Common Items > General.)

  3. Escriba un nombre para el archivo de plantilla.Type a name for your template file.

    Note

    El nombre del archivo de plantilla se usará como nombre de clase en el código generado.The template file name will be used as a class name in the generated code. Por lo tanto, no debe contener espacios ni signos de puntuación.Therefore, it should not have spaces or punctuation.

  4. Haga clic en Agregar.Choose Add.

    Se crea un nuevo archivo que tiene la extensión . TT.A new file is created that has extension .tt. Su propiedad de herramienta personalizada está establecida en TextTemplatingFilePreprocessor.Its Custom Tool property is set to TextTemplatingFilePreprocessor. Contiene las siguientes líneas:It contains the following lines:

    <#@ template language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Collections.Generic" #>
    

Convertir un archivo existente en una plantilla en tiempo de ejecuciónConverting an Existing File to a Run-Time Template

Una buena manera de crear una plantilla es convertir un ejemplo existente de la salida.A good way to create a template is to convert an existing example of the output. Por ejemplo, si la aplicación va a generar archivos HTML, puede empezar por crear un archivo HTML sin formato.For example, if your application will generate HTML files, you can start by creating a plain HTML file. Asegúrese de que funciona correctamente y de que su apariencia es correcta.Make sure that it works correctly and that its appearance is correct. Después, inclúyalo en el proyecto de Visual Studio y conviértalo en una plantilla.Then include it into your Visual Studio project and convert it to a template.

Para convertir un archivo de texto existente en una plantilla en tiempo de ejecuciónTo convert an existing text file to a run-time template

  1. Incluya el archivo en el proyecto de Visual Studio.Include the file into your Visual Studio project. En Explorador de soluciones, en el menú contextual del proyecto, elija agregar > elemento existente.In Solution Explorer, on the shortcut menu of the project, choose Add > Existing Item.

  2. Establezca la propiedad herramientas personalizadas del archivo en TextTemplatingFilePreprocessor.Set the file's Custom Tools property to TextTemplatingFilePreprocessor. En Explorador de soluciones, en el menú contextual del archivo, elija propiedades.In Solution Explorer, on the shortcut menu of the file, choose Properties.

    Note

    Si ya se ha establecido la propiedad, asegúrese de que es TextTemplatingFilePreprocessor y no TextTemplatingFileGenerator.If the property is already set, make sure that it is TextTemplatingFilePreprocessor and not TextTemplatingFileGenerator. Esto puede ocurrir si incluye un archivo que ya tiene la extensión . TT.This can happen if you include a file that already has the extension .tt.

  3. Cambie la extensión de nombre de archivo a . TT.Change the file name extension to .tt. Aunque este paso es opcional, le ayuda a evitar abrir el archivo en un editor incorrecto.Although this step is optional, it helps you avoid opening the file in an incorrect editor.

  4. Quite los espacios o signos de puntuación de la parte principal del nombre de archivo.Remove any spaces or punctuation from the main part of the file name. Por ejemplo, "mi Web Page.tt" sería incorrecto, pero "MyWebPage.tt" es correcto.For example "My Web Page.tt" would be incorrect, but "MyWebPage.tt" is correct. El nombre de archivo se utilizará como nombre de clase en el código generado.The file name will be used as a class name in the generated code.

  5. Inserte la siguiente línea al principio del archivo.Insert the following line at the beginning of the file. Si está trabajando en un proyecto de Visual Basic, reemplace "C#" por "VB".If you are working in a Visual Basic project, replace "C#" with "VB".

    <#@ template language="C#" #>

El contenido de la plantilla en tiempo de ejecuciónThe Content of the Run-Time Template

Directiva de plantillaTemplate directive

Mantenga la primera línea de la plantilla tal como estaba al crear el archivo:Keep the first line of the template as it was when you created the file:

<#@ template language="C#" #>

El parámetro Language dependerá del lenguaje del proyecto.The language parameter will depend on the language of your project.

Contenido sin formatoPlain content

Edite el archivo . TT para que contenga el texto que desea que genere la aplicación.Edit the .tt file to contain the text that you want your application to generate. Por ejemplo:For example:

<html><body>
<h1>Sales for January</h2>
<!-- table to be inserted here -->
This report is Company Confidential.
</body></html>

Código de programa incrustadoEmbedded program code

Puede insertar código de programa entre <# y #>.You can insert program code between <# and #>. Por ejemplo:For example:

<table>
    <# for (int i = 1; i <= 10; i++)
       { #>
         <tr><td>Test name <#= i #> </td>
             <td>Test value <#= i * i #> </td> </tr>
    <# } #>
 </table>
<table>
<#
    For i As Integer = 1 To 10
#>
    <tr><td>Test name <#= i #> </td>
      <td>Test value <#= i*i #> </td></tr>
<#
    Next
#>
</table>

Observe que las instrucciones se insertan entre <# ... #> y se insertan expresiones entre <#= ... #>.Notice that statements are inserted between <# ... #> and expressions are inserted between <#= ... #>. Para obtener más información, vea escribir una plantilla de texto T4.For more information, see Writing a T4 Text Template.

Uso de la plantillaUsing the Template

Código generado a partir de la plantillaThe code built from the template

Al guardar el archivo . TT , se genera un archivo subsidiario . CS o . VB .When you save the .tt file, a subsidiary .cs or .vb file is generated. Para ver este archivo en Explorador de soluciones, expanda el nodo del archivo . TT .To see this file in Solution Explorer, expand the .tt file node. En un proyecto de Visual Basic, en primer lugar, elija Mostrar todos los archivos en la barra de herramientas de Explorador de soluciones .In a Visual Basic project, first choose Show All Files in the Solution Explorer toolbar.

Observe que el archivo subsidiario contiene una clase parcial que contiene un método denominado TransformText().Notice that the subsidiary file contains a partial class that contains a method called TransformText(). Puede llamar a este método desde la aplicación.You can call this method from your application.

Generar texto en tiempo de ejecuciónGenerating text at run time

En el código de la aplicación, puede generar el contenido de la plantilla mediante una llamada como la siguiente:In your application code, you can generate the content of your template using a call like this:

MyWebPage page = new MyWebPage();
String pageContent = page.TransformText();
System.IO.File.WriteAllText("outputPage.html", pageContent);
Dim page = New My.Templates.MyWebPage
Dim pageContent = page.TransformText()
System.IO.File.WriteAllText("outputPage.html", pageContent)

Para colocar la clase generada en un espacio de nombres determinado, establezca la propiedad espacio de nombres de la herramienta personalizada del archivo de plantilla de texto.To place the generated class in a particular namespace, set the Custom Tool Namespace property of the text template file.

Depuración de plantillas de texto en tiempo de ejecuciónDebugging Runtime Text Templates

Depure y pruebe las plantillas de texto en tiempo de ejecución del mismo modo que el código normal.Debug and test runtime text templates in the same way as ordinary code.

Puede establecer un punto de interrupción en una plantilla de texto.You can set a breakpoint in a text template. Si inicia la aplicación en modo de depuración desde Visual Studio, puede recorrer el código y evaluar las expresiones de inspección de la manera habitual.If you start the application in debugging mode from Visual Studio, you can step through the code and evaluate watch expressions in the usual way.

Pasar parámetros en el constructorPassing parameters in the constructor

Normalmente, una plantilla debe importar algunos datos de otras partes de la aplicación.Usually a template must import some data from other parts of the application. Para facilitar esta tarea, el código generado por la plantilla es una clase parcial.To make this easy, the code built by the template is a partial class. Puede crear otra parte de la misma clase en otro archivo del proyecto.You can create another part of the same class in another file in your project. Ese archivo puede incluir un constructor con parámetros, propiedades y funciones a las que puede tener acceso el código que está incrustado en la plantilla y el resto de la aplicación.That file can include a constructor with parameters, properties and functions that can be accessed both by the code that is embedded in the template, and by the rest of the application.

Por ejemplo, puede crear un archivo MyWebPageCode.CSindependiente:For example, you could create a separate file MyWebPageCode.cs:

partial class MyWebPage
{
    private MyData m_data;
    public MyWebPage(MyData data) { this.m_data = data; }}

En el archivo de plantilla MyWebPage.TT, puede escribir:In your template file MyWebPage.tt, you could write:

<h2>Sales figures</h2>
<table>
<# foreach (MyDataItem item in m_data.Items)
   // m_data is declared in MyWebPageCode.cs
   { #>
      <tr><td> <#= item.Name #> </td>
          <td> <#= item.Value #> </td></tr>
<# } // end of foreach
#>
</table>

Para usar esta plantilla en la aplicación:To use this template in the application:

MyData data = ...;
MyWebPage page = new MyWebPage(data);
String pageContent = page.TransformText();
System.IO.File.WriteAllText("outputPage.html", pageContent);

Parámetros de constructor en Visual BasicConstructor parameters in Visual Basic

En Visual Basic, el archivo independiente MyWebPageCode. VB contiene:In Visual Basic, the separate file MyWebPageCode.vb contains:

Namespace My.Templates
  Partial Public Class MyWebPage
    Private m_data As MyData
    Public Sub New(ByVal data As MyData)
      m_data = data
    End Sub
  End Class
End Namespace

El archivo de plantilla podría contener:The template file could contain:

<#@ template language="VB" #>
<html><body>
<h1>Sales for January</h2>
<table>
<#
    For Each item In m_data.Items
#>
    <tr><td>Test name <#= item.Name #> </td>
      <td>Test value <#= item.Value #> </td></tr>
<#
    Next
#>
</table>
This report is Company Confidential.
</body></html>

La plantilla se puede invocar pasando el parámetro en el constructor:The template can invoked by passing the parameter in the constructor:

Dim data = New My.Templates.MyData
    ' Add data values here ....
Dim page = New My.Templates.MyWebPage(data)
Dim pageContent = page.TransformText()
System.IO.File.WriteAllText("outputPage.html", pageContent)

Pasar datos en propiedades de plantillaPassing data in template properties

Una manera alternativa de pasar los datos a la plantilla es agregar propiedades públicas a la clase de plantilla en una definición de clase parcial.An alternative way of passing data to the template is to add public properties to the template class in a partial class definition. La aplicación puede establecer las propiedades antes de invocar TransformText().Your application can set the properties before invoking TransformText().

También puede agregar campos a la clase de plantilla en una definición parcial.You can also add fields to your template class in a partial definition. Esto le permite pasar datos entre ejecuciones sucesivas de la plantilla.This enables you to pass data between successive executions of the template.

Usar clases parciales para el códigoUse partial classes for code

Muchos desarrolladores prefieren evitar escribir grandes cuerpos de código en las plantillas.Many developers prefer to avoid writing large bodies of code in templates. En su lugar, puede definir métodos en una clase parcial que tenga el mismo nombre que el archivo de plantilla.Instead, you can define methods in a partial class that has the same name as the template file. Llame a esos métodos desde la plantilla.Call those methods from the template. De este modo, la plantilla muestra más claramente cuál será el aspecto de la cadena de salida de destino.In this way, the template shows more clearly what the target output string will look like. Las discusiones sobre la apariencia del resultado pueden separarse de la lógica de creación de los datos que muestra.Discussions about the appearance of the result can be separated from the logic of creating the data that it displays.

Ensamblados y referenciasAssemblies and references

Si desea que el código de plantilla haga referencia a un ensamblado .NET u otro ensamblado como System. Xml. dll, agréguelo a las referencias del proyecto de la manera habitual.If you want your template code to reference a .NET or other assembly such as System.Xml.dll, add it to your project's References in the usual manner.

Si desea importar un espacio de nombres de la misma manera que una instrucción using, puede hacerlo con la Directiva import:If you want to import a namespace in the same way as a using statement, you can do this with the import directive:

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

Estas directivas deben colocarse al principio del archivo, inmediatamente después de la Directiva de <#@template.These directives must be placed at the beginning of the file, immediately after the <#@template directive.

Contenido compartidoShared content

Si tiene texto que se comparte entre varias plantillas, puede colocarlo en un archivo independiente e incluirlo en cada archivo en el que debe aparecer:If you have text that is shared between several templates, you can place it in a separate file and include it in each file in which it should appear:

<#@include file="CommonHeader.txt" #>

El contenido incluido puede contener cualquier combinación de código de programa y texto sin formato, y puede contener otras directivas Include y otras directivas.The included content can contain any mixture of program code and plain text, and it can contain other include directives and other directives.

La directiva Include se puede usar en cualquier parte del texto de un archivo de plantilla o un archivo incluido.The include directive can be used anywhere within the text of a template file or an included file.

Herencia entre plantillas de texto en tiempo de ejecuciónInheritance between Run-Time Text Templates

Puede compartir contenido entre plantillas en tiempo de ejecución escribiendo una plantilla de clase base, que puede ser abstracta.You can share content between run-time templates by writing a base class template, which can be abstract. Use el parámetro inherits de la Directiva <@#template#> para hacer referencia a otra clase de plantilla en tiempo de ejecución.Use the inherits parameter of the <@#template#> directive to reference another runtime template class.

Patrón de herencia: fragmentos en métodos baseInheritance pattern: Fragments in Base Methods

En el patrón que se usa en el ejemplo siguiente, tenga en cuenta los puntos siguientes:In the pattern used in the example that follows, notice the following points:

  • La clase base SharedFragments define métodos dentro de los bloques de características de clase <#+ ... #>.The base class SharedFragments defines methods within class feature blocks <#+ ... #>.

  • La clase base no contiene ningún texto libre.The base class contains no free text. En su lugar, todos los bloques de texto se producen dentro de los métodos de características de clase.Instead, all of its text blocks occur inside the class feature methods.

  • La clase derivada invoca los métodos definidos en SharedFragments.The derived class invokes the methods defined in SharedFragments.

  • La aplicación llama al método TextTransform() de la clase derivada, pero no transforma la clase base SharedFragments.The application calls the TextTransform() method of the derived class, but does not transform the base class SharedFragments.

  • Las clases base y derivadas son plantillas de texto en tiempo de ejecución; es decir, la propiedad herramienta personalizada está establecida en TextTemplatingFilePreprocessor.Both the base and derived classes are runtime text templates; that is, the Custom Tool property is set to TextTemplatingFilePreprocessor.

SharedFragments.tt:SharedFragments.tt:

<#@ template language="C#" #>
<#+
protected void SharedText(int n)
{
#>
   Shared Text <#= n #>
<#+
}
// Insert more methods here if required.
#>

MyTextTemplate1.tt:MyTextTemplate1.tt:

<#@ template language="C#" inherits="SharedFragments" #>
begin 1
   <# SharedText(2); #>
end 1

MyProgram.cs:MyProgram.cs:

...
MyTextTemplate1 t1  = new MyTextTemplate1();
string result = t1.TransformText();
Console.WriteLine(result);

La salida resultante:The resulting output:

begin 1
    Shared Text 2
end 1

Patrón de herencia: texto en cuerpo baseInheritance Pattern: Text in Base Body

En este enfoque alternativo al uso de la herencia de plantilla, la mayor parte del texto se define en la plantilla base.In this alternative approach to using template inheritance, the bulk of the text is defined in the base template. Las plantillas derivadas proporcionan datos y fragmentos de texto que caben en el contenido base.The derived templates provide data and text fragments that fit into the base content.

AbstractBaseTemplate1.tt:AbstractBaseTemplate1.tt:

<#@ template language="C#" #>

Here is the description for this derived template:
  <#= this.Description #>

Here is the fragment specific to this derived template:
<#
  this.PushIndent("  ");
  SpecificFragment(42);
  this.PopIndent();
#>
End of common template.
<#+
  // State set by derived class before calling TextTransform:
  protected string Description = "";
  // 'abstract' method to be defined in derived classes:
  protected virtual void SpecificFragment(int n) { }
#>

DerivedTemplate1.tt:DerivedTemplate1.tt:

<#@ template language="C#" inherits="AbstractBaseTemplate1" #>
<#
  // Set the base template properties:
  base.Description = "Description for this derived class";

  // Run the base template:
  base.TransformText();

#>
End material for DerivedTemplate1.

<#+
// Provide a fragment specific to this derived template:

protected override void SpecificFragment(int n)
{
#>
   Specific to DerivedTemplate1 : <#= n #>
<#+
}
#>

Código de la aplicación:Application code:

...
DerivedTemplate1 t1 = new DerivedTemplate1();
string result = t1.TransformText();
Console.WriteLine(result);

Salida resultante:Resulting output:

Here is the description for this derived template:
  Description for this derived class

Here is the fragment specific to this derived template:
     Specific to DerivedTemplate1 : 42
End of common template.
End material for DerivedTemplate1.

Plantillas en tiempo de diseño: Si desea usar una plantilla para generar código que pasa a formar parte de la aplicación, consulte generación de código en tiempo de diseño mediante plantillas de texto T4.Design-time templates: If you want to use a template to generate code that becomes part of your application, see Design-Time Code Generation by using T4 Text Templates.

Las plantillas en tiempo de ejecución se pueden usar en cualquier aplicación donde las plantillas y su contenido se determinan en tiempo de compilación.Run-time templates can be used in any application where the templates and their content are determined at compile time. Pero si desea escribir una extensión de Visual Studio que genere texto a partir de plantillas que cambian en tiempo de ejecución, consulte invocar la transformación de texto en una extensión de vs.But if you want to write a Visual Studio extension that generates text from templates that change at run time, see Invoking Text Transformation in a VS Extension.

Vea tambiénSee also