Generación de código en tiempo de diseño usando las plantillas de texto T4Design-Time Code Generation by using T4 Text Templates

Plantillas de texto T4 de tiempo de diseño permiten generar código de programa y otros archivos en el proyecto de Visual Studio.Design-time T4 text templates let you generate program code and other files in your Visual Studio project. Normalmente, las plantillas se escriben para que varíen el código que generan según los datos de un modelo.Typically, you write the templates so that they vary the code that they generate according to data from a model. Un modelo es un archivo o una base de datos que contiene información esencial sobre los requisitos de la aplicación.A model is a file or database that contains key information about your application's requirements.

Por ejemplo, podría tener un modelo que define un flujo de trabajo, como una tabla o un diagrama.For example, you could have a model that defines a workflow, either as a table or a diagram. A partir del modelo, puede generar el software que ejecuta el flujo de trabajo.From the model, you can generate the software that executes the workflow. Cuando cambian los requisitos del usuario, es fácil debatir el nuevo flujo de trabajo con los usuarios.When your users' requirements change, it is easy to discuss the new workflow with the users. Regenerar el código del flujo de trabajo es más confiable que actualizar el código a mano.Regenerating the code from the workflow is more reliable than updating the code by hand.

Note

Un modelo es un origen de datos que describe un aspecto determinado de una aplicación.A model is a data source that describes a particular aspect of an application. Puede ser cualquier formulario, en cualquier tipo de archivo o base de datos.It can be any form, in any kind of file or database. No tiene que estar en ningún formulario concreto, como un modelo UML o un modelo de lenguaje específico del dominio.It does not have to be in any particular form, such as a UML model or Domain-Specific Language model. Los modelos típicos están en el formulario de tablas o archivos XML.Typical models are in the form of tables or XML files.

Probablemente ya está familiarizado con la generación de código.You are probably already familiar with code generation. Al definir los recursos en un .resx se genera automáticamente el archivo en la solución de Visual Studio, un conjunto de clases y métodos.When you define resources in a .resx file in your Visual Studio solution, a set of classes and methods is generated automatically. El archivo de recursos hace que resulte más fácil y confiable editar los recursos que editar las clases y los métodos.The resources file makes it much easier and more reliable to edit the resources than it would be if you had to edit the classes and methods. Con las plantillas de texto, puede generar código de la misma manera a partir de un origen con un diseño propio.With text templates, you can generate code in the same manner from a source of your own design.

Una plantilla de texto contiene una mezcla del texto que se desea generar y el código de programa que genera partes variables del texto.A text template contains a mixture of the text that you want to generate, and program code that generates variable parts of the text. El código de programa y el texto permiten repetir u omitir condicionalmente partes del texto generado.The program code and allows you to repeat or conditionally omit parts of the generated text. El texto generado por sí mismo puede ser código de programa que formará parte de la aplicación.The generated text can itself be program code that will form part of your application.

Crear una plantilla de texto T4 en tiempo de diseñoCreating a Design-Time T4 Text Template

Para crear una plantilla T4 en tiempo de diseño en Visual StudioTo create a design-time T4 template in Visual Studio

  1. Crear un proyecto de Visual Studio, o abrir uno existente.Create a Visual Studio project, or open an existing one.

    Por ejemplo, en el archivo menú, elija New > proyecto.For example, on the File menu, choose New > Project.

  2. Agregue un archivo de plantilla de texto al proyecto y asígnele un nombre que tenga la extensión .tt.Add a text template file to your project and give it a name that has the extension .tt.

    Para ello, en el Explorador de soluciones, en el menú contextual del proyecto, elija agregar > nuevo elemento.To do this, in Solution Explorer, on the shortcut menu of your project, choose Add > New Item. En el Agregar nuevo elemento cuadro de diálogo seleccione plantilla de texto desde el panel central.In the Add New Item dialog box select Text Template from the middle pane.

    Tenga en cuenta que el Custom Tool es propiedad del archivo TextTemplatingFileGenerator.Notice that the Custom Tool property of the file is TextTemplatingFileGenerator.

  3. Abra el archivo.Open the file. Ya contendrá las siguientes directivas:It will already contain the following directives:

    <#@ template hostspecific="false" language="C#" #>
    <#@ output extension=".txt" #>
    

    Si agregó la plantilla a un proyecto de Visual BasicVisual Basic, el atributo de lenguaje será "VB".If you added the template to a Visual BasicVisual Basic project, the language attribute will be "VB".

  4. Agregue el texto que desee al final del archivo.Add some text at the end of the file. Por ejemplo:For example:

    Hello, world!
    
  5. Guarde el archivo.Save the file.

    Es posible que vea un advertencia de seguridad cuadro de mensaje que le pide que confirme que desea ejecutar la plantilla.You might see a Security Warning message box that asks you to confirm that you want to run the template. Haga clic en Aceptar.Click OK.

  6. En el Explorador de soluciones, expanda el nodo del archivo de plantilla y encontrará un archivo que tiene la extensión .txt.In Solution Explorer, expand the template file node and you will find a file that has the extension .txt. El archivo contiene el texto generado a partir de la plantilla.The file contains the text generated from the template.

    Note

    Si el proyecto es un proyecto de Visual Basic, debe hacer clic en mostrar todos los archivos con el fin de ver el archivo de salida.If your project is a Visual Basic project, you must click Show All Files in order to see the output file.

Volver a generar el códigoRegenerating the code

Se ejecutará una plantilla, que generará el archivo subsidiario, en cualquiera de los siguientes casos:A template will be executed, generating the subsidiary file, in any of the following cases:

  • Edite la plantilla y, a continuación, cambiar el foco a otra ventana de Visual Studio.Edit the template and then change focus to a different Visual Studio window.

  • Guarde la plantilla.Save the template.

  • Haga clic en Transformar todas las plantillas en el compilar menú.Click Transform All Templates in the Build menu. Este modo transformará todas las plantillas de la solución de Visual Studio.This will transform all the templates in the Visual Studio solution.

  • En el Explorador de soluciones, en el menú contextual de cualquier archivo, elija ejecutar herramienta personalizada.In Solution Explorer, on the shortcut menu of any file, choose Run Custom Tool. Utilice este método para transformar un subconjunto seleccionado de plantillas.Use this method to transform a selected subset of templates.

    También puede configurar un proyecto de Visual Studio para que las plantillas se ejecuten cuando han cambiado los archivos de datos que leen.You can also set up a Visual Studio project so that the templates are executed when the data files that they read have changed. Para obtener más información, consulte automáticamente volver a generar el código.For more information, see Regenerating the code automatically.

Generar texto variableGenerating Variable Text

Las plantillas de texto permiten utilizar código de programa para modificar el contenido del archivo generado.Text templates let you use program code to vary the content of the generated file.

Para generar texto utilizando código de programaTo generate text by using program code

  1. Cambie el contenido del archivo .tt:Change the content of the .tt file:

    <#@ template hostspecific="false" language="C#" #>
    <#@ output extension=".txt" #>
    <#int top = 10;
    
    for (int i = 0; i<=top; i++)
    { #>
       The square of <#= i #> is <#= i*i #>
    <# } #>
    
    <#@ template hostspecific="false" language="VB" #>
    <#@ output extension=".txt" #>
    <#Dim top As Integer = 10
    
    For i As Integer = 0 To top
    #>
        The square of <#= i #> is <#= i*i #>
    <#
    Next
    #>
    
  2. Guarde el archivo .tt e inspeccione de nuevo el archivo .txt generado.Save the .tt file, and inspect the generated .txt file again. Muestra los valores elevados al cuadrado de los números del 0 al 10.It lists the squares of the numbers from 0 to 10.

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

    Si escribe el código de generación en Visual BasicVisual Basic, la directiva template debería contener language="VB".If you write the generating code in Visual BasicVisual Basic, the template directive should contain language="VB". "C#" es el valor predeterminado."C#" is the default.

Depurar una plantilla de texto T4 en tiempo de diseñoDebugging a Design-Time T4 Text Template

Para depurar una plantilla de texto:To debug a text template:

  • Inserte debug="true" en la directiva template.Insert debug="true" into the template directive. Por ejemplo:For example:

    <#@ template debug="true" hostspecific="false" language="C#" #>

  • Establezca puntos de interrupción en la plantilla, como si fuera código normal.Set breakpoints in the template, in the same way that you would for ordinary code.

  • Elija depurar plantilla T4 en el menú contextual del archivo de plantilla de texto en el Explorador de soluciones.Choose Debug T4 Template from the shortcut menu of the text template file in Solution Explorer.

    Se ejecutará la plantilla y se detendrá en los puntos de interrupción.The template will run and stop at the breakpoints. Puede examinar las variables y recorrer el código de la forma habitual.You can examine variables and step through the code in the usual way.

Tip

debug="true" hace que el código generado se asigne con más precisión a la plantilla de texto insertando más directivas de numeración de líneas en el código generado.debug="true" makes the generated code map more accurately to the text template, by inserting more line numbering directives into the generated code. Si las omite, los puntos de interrupción pueden detener la ejecución en un estado incorrecto.If you leave it out, breakpoints might stop the run in the wrong state.

Puede dejar la cláusula en la directiva de plantilla incluso aunque no esté realizando la depuración.But you can leave the clause in the template directive even when you are not debugging. Esto solo produce una pequeña caída del rendimiento.This causes only a very small drop in performance.

Generar código o recursos para la soluciónGenerating Code or Resources for Your Solution

Puede generar archivos de programa que varían dependiendo de un modelo.You can generate program files that vary, depending on a model. Un modelo es una entrada como una base de datos, un archivo de configuración, un modelo UML, un modelo DSL u otro origen.A model is an input such as a database, configuration file, UML model, DSL model, or other source. Normalmente genera varios archivos de programa que proceden del mismo modelo.You usually generate several program files are from the same model. Para ello, crea un archivo de plantilla para cada archivo de programa generado y establece que todas las plantillas lean el mismo modelo.To achieve this, you create a template file for each generated program file, and have all the templates read the same model.

Para generar código de programa o recursosTo generate program code or resources

  1. Cambie la directiva de salida para generar un archivo del tipo adecuado, como .cs, .vb, .resx o .xml.Change the output directive to generate a file of the appropriate type, such as .cs, .vb, .resx, or .xml.

  2. Inserte el código que generará el código de solución que requiere.Insert code that will generate the solution code that you require. Por ejemplo, si desea generar tres declaraciones de campo de número entero en una clase:For example, if you want to generate three integer field declarations in a class:

    
    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ output extension=".cs" #>
    <# var properties = new string [] {"P1", "P2", "P3"}; #>
    // This is generated code:
    class MyGeneratedClass {
    <# // This code runs in the text template:
      foreach (string propertyName in properties)  { #>
      // Generated code:
      private int <#= propertyName #> = 0;
    <# } #>
    }
    
    <#@ template debug="false" hostspecific="false" language="VB" #>
    <#@ output extension=".cs" #>
    <# Dim properties = {"P1", "P2", "P3"} #>
    class MyGeneratedClass {
    <#
       For Each propertyName As String In properties
    #>
      private int <#= propertyName #> = 0;
    <#
       Next
    #>
    }
    
    
  3. Guarde el archivo e inspeccione el archivo generado, que ahora contiene el siguiente código:Save the file and inspect the generated file, which now contains the following code:

    class MyGeneratedClass {
      private int P1 = 0;
      private int P2 = 0;
      private int P3 = 0;
    }
    

Generar código y texto generadoGenerating Code and Generated Text

Al generar el código de programa, es muy importante no confundir el código de generación que se ejecuta en la plantilla con el código generado resultante que pasa a formar parte de la solución.When you generate program code, it is most important to avoid confusing the generating code that executes in your template, and the resulting generated code that becomes part of your solution. No es necesario que los dos lenguajes sean iguales.The two languages do not have to be the same.

El ejemplo anterior tiene dos versiones.The previous example has two versions. En una versión, el código de generación es en C#.In one version, the generating code is in C#. En la otra versión, el código de generación es en Visual Basic.In the other version, the generating code is Visual Basic. Sin embargo, el texto generado por ambos es el mismo, y es una clase de C#.But the text generated by both of them is the same, and it is a C# class.

Del mismo modo, podría utilizar una plantilla de Visual C#Visual C# para generar código en cualquier lenguaje.In the same way, you could use a Visual C#Visual C# template to generate code in any language. El texto generado no tiene que estar en un lenguaje determinado, y no tiene que ser código de programa.The generated text does not have to be in any particular language, and it does not have to be program code.

Estructura de plantillas de textoStructuring text templates

Como práctica recomendable, se tiende a separar el código de plantilla en dos partes:As a matter of good practice, we tend to separate the template code into two parts:

  • Una configuración o parte de la recolección de datos, que establece valores en variables, pero no contiene bloques de texto.A configuration or data-gathering part, which sets values in variables, but does not contain text blocks. En el ejemplo anterior, esta parte es la inicialización de properties.In the previous example, this part is the initialization of properties.

    Esto, a veces se denomina la sección "modelo", porque genera un modelo en almacén y lee normalmente un archivo del modelo.This is sometimes called the "model" section, because it constructs an in-store model, and typically reads a model file.

  • La parte de la generación de texto (foreach(...){...} en el ejemplo), que utiliza valores de las variables.The text-generation part (foreach(...){...} in the example), which uses the values of the variables.

    Esta separación no es necesaria, pero es un estilo que facilita la lectura de la plantilla reduciendo la complejidad de la parte que incluye el texto.This is not a necessary separation, but it is a style which makes it easier to read the template by reducing the complexity of the part that includes text.

Leer archivos u otros orígenesReading files or other sources

Para obtener acceso a un archivo modelo o base de datos, el código de plantilla puede utilizar ensamblados como System.XML.To access a model file or database, your template code can use assemblies such as System.XML. Para obtener acceso a estos ensamblados, debe insertar directivas como las siguientes:To gain access to these assemblies, you must insert directives such as these:

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

El assembly directiva hace que el ensamblado especificado esté disponible para el código de plantilla, en la misma manera que la sección de referencias de un proyecto de Visual Studio.The assembly directive makes the specified assembly available to your template code, in the same manner as the References section of a Visual Studio project. No necesita incluir una referencia a System.dll, al que se hace referencia automáticamente.You do not need to include a reference to System.dll, which is referenced automatically. La directiva import permite utilizar tipos sin usar sus nombres completos, de la misma manera que la directiva using en un archivo de programa normal.The import directive lets you use types without using their fully qualified names, in the same manner as the using directive in an ordinary program file.

Por ejemplo, después de importar System.IO, podría escribir:For example, after importing System.IO, you could write:


<# var properties = File.ReadLines("C:\\propertyList.txt");#>
...
<# foreach (string propertyName in properties) { #>
...
<# For Each propertyName As String In
             File.ReadLines("C:\\propertyList.txt")
#>

Abrir un archivo con un nombre de ruta de acceso relativaOpening a file with a relative pathname

Para cargar un archivo de una ubicación relativa a la plantilla de texto, puede utilizar this.Host.ResolvePath().To load a file from a location relative to the text template, you can use this.Host.ResolvePath(). Para utilizar this.Host, debe establecer hostspecific="true" en la template:To use this.Host, you must set hostspecific="true" in the template:

<#@ template debug="false" hostspecific="true" language="C#" #>

A continuación, puede escribir, por ejemplo:Then you can write, for example:

<# string fileName = this.Host.ResolvePath("filename.txt");
  string [] properties = File.ReadLines(filename);
#>
...
<#  foreach (string propertyName in properties { #>
...
<# Dim fileName = Me.Host.ResolvePath("propertyList.txt")
   Dim properties = File.ReadLines(filename)
#>
...
<#   For Each propertyName As String In properties
...
#>

También puede utilizar this.Host.TemplateFile, que identifica el nombre del archivo de plantilla actual.You can also use this.Host.TemplateFile, which identifies the name of the current template file.

El tipo de this.Host (en VB, Me.Host) es Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost.The type of this.Host (in VB, Me.Host) is Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost.

Obtención de datos de Visual StudioGetting data from Visual Studio

Para utilizar servicios proporcionados en Visual Studio, establezca el hostSpecific atributo y carga el EnvDTE ensamblado.To use services provided in Visual Studio, set the hostSpecific attribute and load the EnvDTE assembly. Importación Microsoft.VisualStudio.TextTemplating, que contiene el GetCOMService() método de extensión.Import Microsoft.VisualStudio.TextTemplating, which contains the GetCOMService() extension method. Puede utilizar entonces IServiceProvider.GetCOMService() para tener acceso al DTE y otros servicios.You can then use IServiceProvider.GetCOMService() to access DTE and other services. Por ejemplo:For example:

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#
  IServiceProvider serviceProvider = (IServiceProvider)this.Host;
  EnvDTE.DTE dte = (EnvDTE.DTE) serviceProvider.GetCOMService(typeof(EnvDTE.DTE));
#>

Number of projects in this VS solution:  <#= dte.Solution.Projects.Count #>

Tip

Una plantilla de texto se ejecuta en su propio dominio de aplicación y el acceso a los servicios se realiza mediante el cálculo de referencias.A text template runs in its own app domain, and services are accessed by marshaling. En este caso, GetCOMService() es más confiable que GetService().In this circumstance, GetCOMService() is more reliable than GetService().

Volver a generar el código automáticamenteRegenerating the code automatically

Normalmente, se generan varios archivos en una solución de Visual Studio con un modelo de entrada.Typically, several files in a Visual Studio solution are generated with one input model. Cada archivo se genera a partir de su propia plantilla, pero todas las plantillas hacen referencia al mismo modelo.Each file is generated from its own template, but the templates all refer to the same model.

Si el modelo de origen cambia, debe volver a ejecutar todas las plantillas de la solución.If the source model changes, you should re-run all the templates in the solution. Para hacerlo manualmente, elija Transformar todas las plantillas en el compilar menú.To do this manually, choose Transform All Templates on the Build menu.

Si ha instalado el SDK de modelado de Visual Studio, puede tener todas las plantillas se transformen automáticamente cada vez que realice una compilación.If you have installed the Visual Studio Modeling SDK, you can have all the templates transformed automatically whenever you perform a build. Para ello, edite el archivo de proyecto (.csproj o .vbproj) en un editor de texto y agregue las siguientes líneas cerca del final del archivo, después de cualquier otra instrucción <import>:To do this, edit your project file (.csproj or .vbproj) in a text editor and add the following lines near the end of the file, after any other <import> statements:

Note

En Visual Studio 2017, el SDK de transformación de plantilla de texto y el SDK de modelado de Visual Studio se instalan automáticamente al instalar características específicas de Visual Studio.In Visual Studio 2017, the Text Template Transformation SDK and the Visual Studio Modeling SDK are installed automatically when you install specific features of Visual Studio. Para obtener más información, consulte esta entrada de blog.For more details, see this blog post.

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\TextTemplating\Microsoft.TextTemplating.targets" />
<PropertyGroup>
   <TransformOnBuild>true</TransformOnBuild>
   <!-- Other properties can be inserted here -->
</PropertyGroup>

Para obtener más información, consulte generación de código en un proceso de compilación.For more information, see Code Generation in a Build Process.

Notificación de erroresError reporting

Para colocar mensajes de error y advertencia en la ventana de errores de Visual Studio, puede utilizar estos métodos:To place error and warning messages in the Visual Studio error window, you can use these methods:

Error("An error message");
Warning("A warning message");

Convertir un archivo existente en una plantillaConverting an existing file to a template

Una característica útil de las plantillas es que se parecen mucho a los archivos que generan y cuentan con algún código de programa insertado.A useful feature of templates is that they look very much like the files that they generate, together with some inserted program code. Esto sugiere un método útil para crear una plantilla.This suggests a useful method of creating a template. En primer lugar cree un archivo normal como prototipo, como un Visual C#Visual C# de archivo y, a continuación, agregue gradualmente código de generación que modifique el archivo resultante.First create an ordinary file as a prototype, such as a Visual C#Visual C# file, and then gradually introduce generation code that varies the resulting file.

Para convertir un archivo existente en una plantilla en tiempo de diseñoTo convert an existing file to a design-time template

  1. A su proyecto de Visual Studio, agregue un archivo del tipo que desea generar, como un .cs, .vb, o .resx archivo.To your Visual Studio project, add a file of the type that you want to generate, such as a .cs, .vb, or .resx file.

  2. Pruebe el nuevo archivo para asegurarse de que funciona.Test the new file to make sure that it works.

  3. En el Explorador de soluciones, cambie la extensión de nombre de archivo a .tt.In Solution Explorer, change the file name extension to .tt.

  4. Compruebe las siguientes propiedades de la .tt archivo:Verify the following properties of the .tt file:

    Herramienta personalizada =Custom Tool = TextTemplatingFileGeneratorTextTemplatingFileGenerator
    Acción de compilación =Build Action = NingunoNone
  5. Inserte las siguientes líneas al principio del archivo:Insert the following lines at the beginning of the file:

    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ output extension=".cs" #>
    

    Si desea escribir el código de generación de la plantilla en Visual BasicVisual Basic, establezca el atributo language en "VB" en lugar de "C#".If you want to write the generating code of your template in Visual BasicVisual Basic, set the language attribute to "VB" instead of "C#".

    Establezca el atributo extension en la extensión de nombre de archivo para el tipo de archivo que desea generar, por ejemplo .cs, .resx o .xml.Set the extension attribute to the file name extension for the type of file that you want to generate, for example .cs, .resx, or .xml.

  6. Guarde el archivo.Save the file.

    Se crea un archivo subsidiario, con la extensión especificada.A subsidiary file is created, with the specified extension. Sus propiedades son correctas para el tipo de archivo.Its properties are correct for the type of file. Por ejemplo, el acción de compilación propiedad de un archivo .cs sería compilar.For example, the Build Action property of a .cs file would be Compile.

    Compruebe que el archivo generado incluye el mismo contenido que el archivo original.Verify that the generated file contains the same content as the original file.

  7. Identifique una parte del archivo que desea modificar.Identify a part of the file that you want to vary. Por ejemplo, una parte que aparece solamente bajo ciertas condiciones o una parte que se repite o donde los valores concretos varían.For example, a part that appears only under certain conditions, or a part that is repeated, or where the specific values vary. Inserte el código de generación.Insert generating code. Guarde el archivo y compruebe que el archivo subsidiario se genera correctamente.Save the file and verify that the subsidiary file is correctly generated. Repita este paso.Repeat this step.

Directrices para la generación de códigoGuidelines for Code Generation

Consulte directrices para escribir plantillas de texto T4.Please see Guidelines for Writing T4 Text Templates.

Pasos siguientesNext steps

Paso siguienteNext step TemaTopic
Escriba y depure una plantilla de texto más avanzada, con código que utilice funciones auxiliares, archivos incluidos y datos externos.Write and debug a more advanced text template, with code that uses auxiliary functions, included files, and external data. Escribir una plantilla de texto T4Writing a T4 Text Template
Genere documentos a partir de plantillas en tiempo de ejecución.Generate documents from templates at run time. Generación de texto en tiempo de ejecución con plantillas de texto T4Run-Time Text Generation with T4 Text Templates
Ejecute la generación de texto fuera de Visual Studio.Run text generation outside Visual Studio. Generar archivos con la utilidad TextTransformGenerating Files with the TextTransform Utility
Transforme los datos al formato de un lenguaje específico de dominio.Transform your data in the form of a domain-specific language. Generar código a partir de lenguajes específicos de dominioGenerating Code from a Domain-Specific Language
Escriba procesadores de directivas para transformar sus propios orígenes de datos.Write directive processors to transform your own data sources. Personalizar la transformación de texto T4Customizing T4 Text Transformation

Vea tambiénSee Also