Appeler la transformation de texte dans le processus de génération

Vous pouvez appeler la transformation de texte dans le cadre du processus de génération d’une solution Visual Studio. Il existe des tâches de génération qui sont spécialisées pour la transformation de texte. Les tâches de génération T4 exécutent les modèles de texte au moment du design. En outre, elles compilent les modèles de texte (prétraités) au moment de l’exécution.

Il existe quelques différences en matière de possibilités offertes par les tâches de génération, selon le moteur de génération que vous utilisez. Lorsque vous générez la solution dans Visual Studio, un modèle de texte peut accéder à l’API Visual Studio (EnvDTE) si l’attribut hostspecific="true" est défini. Mais cela n’est pas vrai lorsque vous générez la solution à partir de la ligne de commande ou lorsque vous démarrez une génération serveur via Visual Studio. Dans ces situations, la génération est exécutée par MSBuild et un autre hôte T4 est utilisé. Cela signifie que vous ne pouvez pas accéder aux éléments comme les noms de fichiers projet de la même manière lorsque vous générez un modèle de texte avec MSBuild. Toutefois, vous pouvez passer les informations d’environnement aux modèles de texte et aux processeurs de directive en utilisant les paramètres de build.

Configurer vos ordinateurs

Pour permettre les tâches de génération sur votre ordinateur de développement, installez le SDK Modeling pour Visual Studio.

Notes

Le composant Transformation de modèle de texte est automatiquement installé dans le cadre de la charge de travail Développement d’extensions Visual Studio. Vous pouvez aussi l’installer à partir de l’onglet Composants individuels de Visual Studio Installer, sous la catégorie SDK, bibliothèques et frameworks. Installez le composant Modélisation de SDK à partir de l’onglet Composants individuels.

Si votre serveur de builds s’exécute sur un ordinateur sur lequel Visual Studio n’est pas installé, copiez les fichiers suivants sur l’ordinateur de build à partir de votre ordinateur de développement :

  • %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

Conseil

Si vous obtenez un MissingMethodException pour une méthode Microsoft.CodeAnalysis lors de l’exécution des cibles de génération TextTemplating sur un serveur de build, assurez-vous que les assemblys Roslyn se trouvent dans un répertoire nommé Roslyn qui se trouve dans le même répertoire que l’exécutable de build (par exemple, msbuild.exe).

Modifier le fichier projet

Modifiez votre fichier projet pour configurer certaines des fonctionnalités de MSBuild, par exemple, l’importation des cibles de transformation de texte.

Dans l’Explorateur de solutions, choisissez Décharger dans le menu contextuel de votre projet. Cela vous permet de modifier le fichier .csproj ou .vbproj dans l'éditeur XML. Lorsque vous avez terminé la modification, choisissez Recharger.

Importation des cibles de la transformation de texte

Dans le fichier .vbproj ou .csproj, recherchez la dernière ligne Import Project.

Après cette ligne, si elle existe, insérez l’importation de modèles de texte :

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

Transformation des modèles d’une build

Il existe des propriétés que vous pouvez insérer dans votre fichier projet afin de contrôler la tâche de transformation :

  • Exécutez la tâche de transformation au début de chaque génération :

    <PropertyGroup>
        <TransformOnBuild>true</TransformOnBuild>
    </PropertyGroup>
    
  • Remplacez les fichiers en lecture seule, par exemple, car ils ne sont pas vérifiés :

    <PropertyGroup>
        <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
    </PropertyGroup>
    
  • Transformez chaque modèle à chaque fois :

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

    Par défaut, la tâche MSBuild T4 régénère un fichier de sortie s’il est antérieur à :

    • son fichier de modèle
    • tous les fichiers inclus
    • tous les fichiers qui ont été précédemment lus par le modèle ou par un processeur de directives qu’il utilise

    Il s’agit d’un test de dépendance beaucoup plus puissant que celui de la commande Transformer tous les modèles dans Visual Studio. Ce dernier ne fait que comparer les dates du fichier modèle et du fichier de sortie.

Pour exécuter uniquement les transformations de texte dans votre projet, appelez la tâche TransformAll :

msbuild myProject.csproj /t:TransformAll

Pour transformer un modèle de texte spécifique :

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

Vous pouvez utiliser des caractères génériques dans TransformFile :

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

Contrôle de code source

Il n'existe aucune intégration prédéfinie spécifique avec un système de contrôle de code source. Toutefois, vous pouvez ajouter vos propres extensions, par exemple, pour extraire et archiver un fichier généré. Par défaut, la tâche de transformation de texte évite de remplacer un fichier marqué en lecture seule. Lorsqu’un tel fichier est rencontré, une erreur est enregistrée dans la liste d’erreurs Visual Studio et la tâche échoue.

Pour spécifier que les fichiers en lecture seule doivent être remplacés, insérez la propriété suivante :

<OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>

À moins que vous ne personnalisiez l’étape de post-traitement, un avertissement sera consigné dans la liste d’erreurs lorsqu’un fichier est remplacé.

Personnalisation du processus de génération

La transformation de texte se produit avant les autres tâches du processus de génération. Pour définir les tâches appelées avant et après la transformation, définissez les propriétés $(BeforeTransform) et $(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>

Dans AfterTransform, vous pouvez référencer des listes de fichiers :

  • GeneratedFiles : liste des fichiers écrits par le processus. Pour ces fichiers qui remplacent les fichiers en lecture seule existants, %(GeneratedFiles.ReadOnlyFileOverwritten) aura la valeur true. Ces fichiers peuvent être extraits du contrôle de code source.

  • NonGeneratedFiles : liste des fichiers en lecture seule qui n'ont pas été remplacés.

Par exemple, vous définissez une tâche afin d'extraire GeneratedFiles.

OutputFilePath et OutputFileName

Ces propriétés sont utilisées uniquement par MSBuild. Elles n'affectent pas la génération du code dans Visual Studio. Elles redirigent le fichier de sortie généré vers un autre dossier ou fichier. Le dossier cible doit déjà exister.

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

$(IntermediateOutputPath) est un dossier utile pour la redirection.

Si vous spécifiez un nom de fichier de sortie, il est prioritaire par rapport à l’extension spécifiée dans la directive de sortie des modèles.

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

Il est déconseillé de spécifier OutputFileName ou OutputFilePath si vous transformez également des modèles dans Visual Studio via la commande Transformer tous les modèles, ou si vous exécutez le générateur de fichier unique. Vous obtiendrez des chemins d’accès de fichiers distincts selon la façon dont vous avez déclenché la transformation. Ceci peut prêter à confusion.

Ajout de chemins d’accès des références et Include

L’hôte possède un ensemble de chemins d’accès par défaut dans lesquels il recherche les assemblys référencés dans les modèles. Pour effectuer un ajout à cet ensemble :

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

Pour définir les dossiers où rechercher les fichiers Include, fournissez une liste d'éléments délimités par des points-virgules. Généralement, vous effectuez l'ajout à la liste des dossiers existants.

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

Passer les données de contexte de build dans les modèles

Vous pouvez définir des valeurs de paramètre dans le fichier projet. Par exemple, vous pouvez passer des propriétés de build et des variables d’environnement :

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

Dans un modèle de texte, définissez hostspecific dans la directive de modèle. Utilisez la directive parameter pour obtenir des valeurs :

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

Dans un processeur de directive, vous pouvez appeler ITextTemplatingEngineHost.ResolveParameterValue :

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

Notes

ResolveParameterValue obtient des données uniquement à partir de T4ParameterValues lorsque vous utilisez MSBuild. Lorsque vous transformez le modèle à l’aide de Visual Studio, les paramètres ont des valeurs par défaut.

Utilisation de propriétés de projet dans les directives d’assembly et Include

Les macros Visual Studio comme $(SolutionDir) ne fonctionnent pas dans MSBuild. Vous pouvez utiliser des propriétés de projet à la place.

Modifiez votre fichier .csproj ou.vbproj pour définir une propriété de projet. Cet exemple définit une propriété nommée 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>

Désormais, vous pouvez utiliser votre propriété de projet dans les directives d'assembly et Include :

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

Ces directives obtiennent des valeurs à partir de T4parameterValues dans MSBuild et les hôtes Visual Studio.

Questions et réponses

Pourquoi vouloir transformer des modèles sur le serveur de builds ? J'ai déjà transformé des modèles dans Visual Studio avant d'archiver mon code.

Si vous mettez à jour un fichier inclus ou tout autre fichier lu par le modèle, Visual Studio ne transforme pas le fichier automatiquement. La transformation des modèles dans le cadre de la build permet de s’assurer que tout est à jour.

Quelles sont les autres options en matière de transformation de modèles de texte ?

  • Vous trouverez de bons conseils dans le modèle T4 MSbuild dans %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VisualStudio\v17.0\TextTemplating\Microsoft.TextTemplating.targets
  • Vous trouverez de bons conseils dans le modèle T4 MSbuild dans %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\msbuild\Microsoft\VisualStudio\v16.0\TextTemplating\Microsoft.TextTemplating.targets