Invocación de la transformación de texto en el proceso de compilación

Se puede invocar la transformación de texto como parte del proceso de compilación de una solución de Visual Studio. Hay tareas de compilación que están especializadas para la transformación de texto. Las tareas de compilación T4 ejecutan plantillas de texto en tiempo de diseño y también compilan plantillas de texto en tiempo de ejecución (preprocesadas).

Hay algunas diferencias en cuanto a lo que las tareas de compilación pueden hacer, según el motor de compilación que utilice. Cuando se compila la solución en Visual Studio, una plantilla de texto puede tener acceso a la API de Visual Studio (EnvDTE) si se establece el atributo hostspecific="true". Pero eso no es cierto cuando se compila la solución desde la línea de comandos o cuando se inicia un servidor compilado mediante Visual Studio. En esos casos, la compilación la realiza MSBuild y se utiliza un host T4 diferente. Esto significa que no puede tener acceso a elementos como nombres de archivo de proyecto de la misma manera cuando se compila una plantilla de texto mediante MSBuild. Sin embargo, puede pasar información de entorno en plantillas de texto y procesadores de directivas mediante parámetros de compilación.

Configurar los equipos

Para habilitar las tareas de compilación en el equipo de desarrollo, instale el SDK de modelado de Visual Studio.

Nota

El componente Transformación de plantilla de texto se instala de forma automática como parte de la carga de trabajo Desarrollo de extensiones de Visual Studio. También lo puede instalar desde la pestaña Componentes individuales del Instalador de Visual Studio, en la categoría SDK, bibliotecas y marcos. Instale el componente SDK de modelado desde la pestaña Componentes individuales.

Si su servidor de compilación se ejecuta en un equipo en el que no está instalado Visual Studio, copie los siguientes archivos en el equipo de compilación desde el equipo de desarrollo:

  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VisualStudio\v16.0\TextTemplating

    • Microsoft.VisualStudio.TextTemplating.Sdk.Host.15.0.dll
    • Microsoft.TextTemplating.Build.Tasks.dll
    • Microsoft.TextTemplating.targets
  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0

    • Microsoft.VisualStudio.TextTemplating.15.0.dll
    • Microsoft.VisualStudio.TextTemplating.Interfaces.15.0.dll
    • Microsoft.VisualStudio.TextTemplating.VSHost.15.0.dll
  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\Common7\IDE\PublicAssemblies

    • Microsoft.VisualStudio.TextTemplating.Modeling.15.0.dll

Sugerencia

Si obtiene un elemento MissingMethodException para un método Microsoft.CodeAnalysis al ejecutar destinos de compilación TextTemplating en un servidor de compilación, asegúrese de que los ensamblados de Roslyn están en un directorio denominado Roslyn que se encuentra en el mismo directorio que el ejecutable de compilación (por ejemplo, msbuild.exe).

Edición del archivo del proyecto

Edite el archivo de proyecto para configurar algunas de las características de MSBuild, por ejemplo, importe los destinos de transformación de texto.

En el Explorador de soluciones, elija Descargar en el menú contextual del proyecto. Esto permite editar el archivo .csproj o .vbproj en el editor XML. Después de finalizar la edición, elija Recargar.

Importación de los destinos de transformación de texto

En el archivo .vbproj o .csproj, busque la última línea Import Project.

Después de esa línea, si existe, inserte la importación de plantillas de texto:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v17.0\TextTemplating\Microsoft.TextTemplating.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v16.0\TextTemplating\Microsoft.TextTemplating.targets" />

Transformación de plantillas en una compilación

Hay algunas propiedades que se pueden insertar en el archivo de proyecto para controlar la tarea de transformación:

  • Ejecute la tarea de transformación al principio de cada compilación:

    <PropertyGroup>
        <TransformOnBuild>true</TransformOnBuild>
    </PropertyGroup>
    
  • Sobrescriba los archivos que son de solo lectura, por ejemplo, porque no se han desprotegido:

    <PropertyGroup>
        <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
    </PropertyGroup>
    
  • Transforme todas las plantillas cada vez:

    <PropertyGroup>
        <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
    </PropertyGroup>
    

    De forma predeterminada, la tarea de MSBuild de T4 regenera un archivo de salida si es más antiguo que:

    • Su archivo de plantilla
    • Cualquier archivo que se ha incluido
    • Cualquier archivo que ha leído previamente la plantilla o un procesador de directivas que usa

    Esto es una prueba de dependencia más eficaz que la utilizada por el comando Transformar todas las plantillas de Visual Studio, que solo compara las fechas de la plantilla y del archivo de salida.

Para realizar solo las transformaciones de texto en el proyecto, invoque la tarea TransformAll:

msbuild myProject.csproj /t:TransformAll

Para transformar una plantilla de texto específica:

msbuild myProject.csproj /t:Transform /p:TransformFile="Template1.tt"

Puede utilizar caracteres comodín en TransformFile:

msbuild dsl.csproj /t:Transform /p:TransformFile="GeneratedCode\**\*.tt"

Control de código fuente

No hay ninguna integración específica con un sistema de control de código fuente. Sin embargo, puede agregar sus propias extensiones, por ejemplo para extraer e insertar en el repositorio un archivo generado. De forma predeterminada, la tarea de transformación de texto evita sobrescribir un archivo marcado como solo lectura. Cuando se encuentra un archivo de este tipo, se registra un error en la ventana Lista de errores de Visual Studio y se produce un error en la tarea.

Para especificar que los archivos de solo lectura se deben sobrescribir, inserte esta propiedad:

<OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>

A menos que personalice el paso de procesamiento posterior, se registrará una advertencia en la Lista de errores cuando se sobrescriba un archivo.

Personalización del proceso de compilación

La transformación de texto se realiza antes que otras tareas del proceso de compilación. Para definir las tareas que se invocan antes y después de la transformación, establezca las propiedades $(BeforeTransform) y $(AfterTransform):

<PropertyGroup>
    <BeforeTransform>CustomPreTransform</BeforeTransform>
    <AfterTransform>CustomPostTransform</AfterTransform>
</PropertyGroup>
<Target Name="CustomPreTransform">
    <Message Text="In CustomPreTransform..." Importance="High" />
</Target>
<Target Name="CustomPostTransform">
    <Message Text="In CustomPostTransform..." Importance="High" />
</Target>

En AfterTransform, se puede hacer referencia a listas de archivos:

  • GeneratedFiles: lista de archivos en los que ha escrito el proceso. En los archivos que sobrescriben archivos existentes de solo lectura, %(GeneratedFiles.ReadOnlyFileOverwritten) será true. Estos archivos se pueden desproteger del control de código fuente.

  • NonGeneratedFiles: lista de archivos de solo lectura que no se sobrescribieron.

Por ejemplo, defina una tarea para extraer del repositorio GeneratedFiles.

OutputFilePath y OutputFileName

Estas propiedades solo las utiliza MSBuild. No afectan a la generación de código en Visual Studio. Redirigen el archivo de salida generado a otra carpeta o archivo. La carpeta de destino debe existir.

<ItemGroup>
  <None Include="MyTemplate.tt">
    <Generator>TextTemplatingFileGenerator</Generator>
    <OutputFilePath>MyFolder</OutputFilePath>
    <LastGenOutput>MyTemplate.cs</LastGenOutput>
  </None>
</ItemGroup>

Una carpeta útil como destino de la redirección es $(IntermediateOutputPath).

Si especifica un nombre de archivo de salida, este tiene prioridad sobre la extensión especificada en la directiva de salida en las plantillas.

<ItemGroup>
  <None Include="MyTemplate.tt">
    <Generator>TextTemplatingFileGenerator</Generator>
    <OutputFileName>MyOutputFileName.cs</OutputFileName>
    <LastGenOutput>MyTemplate.cs</LastGenOutput>
  </None>
</ItemGroup>

No se recomienda especificar OutputFileName o OutputFilePath si va a transformar también plantillas en Visual Studio mediante Transformar todas las plantillas o si va a ejecutar el generador de un solo archivo. Terminará con diferentes rutas de acceso de archivos en función de cómo desencadenara la transformación. Esto puede resultar confuso.

Adición de rutas de acceso de referencia e inclusión

El host tiene un conjunto predeterminado de rutas de acceso donde busca los ensamblados a los que se hace referencia en las plantillas. Para agregar rutas de acceso a este conjunto:

<ItemGroup>
    <T4ReferencePath Include="$(VsIdePath)PublicAssemblies\" />
    <!-- Add more T4ReferencePath items here -->
</ItemGroup>

Para establecer las carpetas en las que se buscarán archivos de inclusión, proporcione una lista separada por signos de puntos y coma. Normalmente se agregan a la lista de carpetas existente.

<PropertyGroup>
    <IncludeFolders>
$(IncludeFolders);$(MSBuildProjectDirectory)\Include;AnotherFolder;And\Another</IncludeFolders>
</PropertyGroup>

Pasar datos de contexto de compilación en las plantillas

Puede establecer valores de parámetro en el archivo de proyecto. Por ejemplo, puede pasar propiedades de compilación y variables de entorno:

<ItemGroup>
  <T4ParameterValues Include="ProjectFolder">
    <Value>$(ProjectDir)</Value>
    <Visible>false</Visible>
  </T4ParameterValues>
</ItemGroup>

En una plantilla de texto, establezca hostspecific en la directiva de plantilla. Use la directiva parameter para obtener valores:

<#@template language="c#" hostspecific="true"#>
<#@ parameter type="System.String" name="ProjectFolder" #>
The project folder is: <#= ProjectFolder #>

En un procesador de directivas, puede llamar a ITextTemplatingEngineHost.ResolveParameterValue:

string value = Host.ResolveParameterValue("-", "-", "parameterName");

Nota

ResolveParameterValue obtiene datos de T4ParameterValues solo cuando se usa MSBuild. Cuando se transforma la plantilla mediante Visual Studio, los parámetros tienen sus valores predeterminados.

Uso de propiedades del proyecto en las directivas de ensamblado e inclusión

Las macros de Visual Studio, como $(SolutionDir), no funcionan en MSBuild. En su lugar, puede utilizar las propiedades del proyecto.

Modifique el archivo .csproj o .vbproj para definir una propiedad de proyecto. En este ejemplo se define una propiedad denominada myLibFolder:

<!-- Define a project property, myLibFolder: -->
<PropertyGroup>
    <myLibFolder>$(MSBuildProjectDirectory)\..\libs</myLibFolder>
</PropertyGroup>

<!-- Tell the MSBuild T4 task to make the property available: -->
<ItemGroup>
    <T4ParameterValues Include="myLibFolder">
      <Value>$(myLibFolder)</Value>
    </T4ParameterValues>
  </ItemGroup>

Ahora puede usar la propiedad del proyecto en directivas de ensamblado e inclusión:

<#@ assembly name="$(myLibFolder)\MyLib.dll" #>
<#@ include file="$(myLibFolder)\MyIncludeFile.t4" #>

Estas directivas obtienen valores de T4parameterValues tanto en hosts de MSBuild y como en hosts de Visual Studio.

Preguntas y respuestas

¿Por qué desearía transformar plantillas en el servidor de compilación? Ya he transformado plantillas en Visual Studio antes de proteger el código.

Si actualiza un archivo incluido, u otro archivo leído por la plantilla, Visual Studio no transforma el archivo automáticamente. La transformación de plantillas como parte de la compilación se asegura de que todo está actualizado.

¿Qué otras opciones existen para transformar plantillas de texto?

  • Encontrará instrucciones de calidad sobre la plantilla T4 de MSBuild en %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VisualStudio\v17.0\TextTemplating\Microsoft.TextTemplating.targets
  • Encontrará instrucciones de calidad sobre la plantilla T4 de MSBuild en %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\msbuild\Microsoft\VisualStudio\v16.0\TextTemplating\Microsoft.TextTemplating.targets