.Net Core 项目中的 TextTemplate 目标

问题描述 投票:0回答:5

我最近将一个测试项目迁移到.NET Core 2.0。该测试项目使用文本模板生成一些重复代码。之前的项目有一个构建目标,用于在构建之前生成所有 T4 模板。因此,生成的代码也不会签入 VCS。

我在项目中使用了此代码片段来确保构建模板:

<PropertyGroup>
  <!-- Default VisualStudioVersion to 15 (VS2017) -->
  <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
  <!-- Determinate VSToolsPath -->
  <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  <!-- Run T4 generation if there are outdated files -->
  <TransformOnBuild>True</TransformOnBuild>
  <TransformOutOfDateOnly>True</TransformOutOfDateOnly>
</PropertyGroup>
<!-- Import TextTemplating target -->
<Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" />

我的第一个方法是保留此片段并将其复制到新的 .NET Core 项目文件中。

在 Visual Studio 中,这是有效的,因为显然

VSToolsPath
设置正确。但是,当我运行 .NET Core SDK 工具时,例如
dotnet test
(正如我在构建服务器上所做的那样),
VSToolsPath
映射到
Program Files\dotnet\sdk\2.0.3
,并且无法找到文本模板目标。

因为这不起作用,我还尝试简单地从 Nuget 安装

Microsoft.VisualStudio.TextTemplating
包,但这有两个问题:

  1. 它并不正式支持 .NET Core,而是针对 .NET 4.6.1 和
  2. 安装
  3. Nuget似乎没有安装任何东西,所以我无法调整项目文件中的路径。
visual-studio-2017 .net-core t4
5个回答
5
投票

要在构建

dotnet build
时支持构建 T4 模板,您需要使用
Custom Text Template Host
,它已经存在于 .NET Core 中 (https://github.com/atifaziz/t5)。要包含它,请将此元素添加到您的项目中的任意
ItemGroup
中:
<DotNetCliToolReference Include="T5.TextTransform.Tool" Version="1.1.0-*" />
。 由于 Visual Studio 已经拥有自己的
Text Template Host
实现,因此您添加的元素应仅适用于 .NET Core。例如:

<ItemGroup Condition="'$(MSBuildRuntimeType)'=='Core'">
    <DotNetCliToolReference Include="T5.TextTransform.Tool" Version="1.1.0-*" />
</ItemGroup>

同时,您应该在 .NET Core 之外调整 Visual Studio 文本模板主机的设置,如下所示:

Condition="'$(MSBuildRuntimeType)'=='Full'"

您还应该在导入

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" Condition="'$(MSBuildRuntimeType)'=='Full'" />
之前添加
Microsoft.TextTemplating.targets
,以使一切在 Visual Studio 中与 .NET Core
csproj
正常工作。

如果您需要清理所有生成的代码,您应该将模板从

*.tt
重命名为
*.Generated.tt
,所有代码将在
*.Generated.cs
下生成,并且可以在
 过滤掉这些文件dotnet clean
行动。

它在您的

csproj
中的完整示例:

<!-- T4 build support for .NET Core (Begin) -->

<ItemGroup Condition="'$(MSBuildRuntimeType)'=='Core'">
  <DotNetCliToolReference Include="T5.TextTransform.Tool" Version="1.1.0-*" />
  <TextTemplate Include="**\*.Generated.tt" />
  <Generated Include="**\*.Generated.cs" />
</ItemGroup>

<Target Name="TextTemplateTransform" BeforeTargets="BeforeBuild" Condition="'$(MSBuildRuntimeType)'=='Core'">
  <ItemGroup>
    <Compile Remove="**\*.cs" />
  </ItemGroup>
  <Exec WorkingDirectory="$(ProjectDir)" Command="dotnet tt %(TextTemplate.Identity)" />
  <ItemGroup>
    <Compile Include="**\*.cs" />
  </ItemGroup>
</Target>

<Target Name="TextTemplateClean" AfterTargets="Clean">
  <Delete Files="@(Generated)" />
</Target>

<!-- T4 build support for .NET Core (End) -->


<!-- T4 build support for Visual Studio (Begin) -->

<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Full'">
  <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  <!-- This is what will cause the templates to be transformed when the project is built (default is false) -->
  <TransformOnBuild>true</TransformOnBuild>
  <!-- Set to true to force overwriting of read-only output files, e.g. if they're not checked out (default is false) -->
  <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
  <!-- Set to false to transform files even if the output appears to be up-to-date (default is true)  -->
  <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
</PropertyGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" Condition="'$(MSBuildRuntimeType)'=='Full'" />
<Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" Condition="'$(MSBuildRuntimeType)'=='Full'" />

<!-- T4 build support for Visual Studio (End) -->

如果您不想重命名模板文件并且不需要清理它们,则替换:

  <TextTemplate Include="**\*.Generated.tt" />
  <Generated Include="**\*.Generated.cs" />

与:

  <TextTemplate Include="**\*.tt" />

并删除:

<Target Name="TextTemplateClean" AfterTargets="Clean">
  <Delete Files="@(Generated)" />
</Target>

欲了解更多信息,请参阅:

如何在

dotnet build
上设置代码生成: https://notquitepure.info/2018/12/12/T4-Templates-at-Build-Time-With-Dotnet-Core/

如何在 Visual Studio 和 .NET Core 的构建中设置代码生成

csproj
https://thomaslevesque.com/2017/11/13/transform-t4-templates-as-part-of-the-build-and-pass-variables-from-the-project/

从单个 T4 模板生成多个文件的完整示例: https://github.com/Konard/T4GenericsExample

更新:

GitHub.com/Mono/T4 更好


1
投票

你受制于为 dotnet core 编写端口的人。

这是旧的:http://www.bricelam.net/2015/03/12/t4-on-aspnet5.html

或者完全使用不同的模板工具,当然我理解如果这不是一个选择。


1
投票

或者只使用T4执行器。您可以设置在构建之前、构建之后执行哪些模板或忽略特定模板。与 VS2017-19 配合良好


1
投票

扩展Konard 的评论“更新:https://github.com/mono/t4 更好。”

安装 Mono/T4 (dotnet-t4) 作为工具

  • 如果您正在运行 Azure DevOps 管道,则可以将其添加为一个步骤 - 请参阅https://stackoverflow.com/a/60667867/1901857的第一部分。

  • 如果您在 Linux dockerfile 中构建,请在构建之前添加此内容(我们在 alpine 上使用 .net 6,但其他发行版和版本应该没问题):

# you will see a warning if this folder is not on PATH
ENV PATH="${PATH}:/root/.dotnet/tools"
RUN dotnet tool install -g dotnet-t4
  • 如果您想在开发计算机上使用该工具,而不是 VS TextTemplated,请从 powershell 运行一次性安装(但团队中的每个开发人员都需要执行此操作):
dotnet tool install -g dotnet-t4

在构建-开发机器和管道上运行 t4

dotnet-t4 的设置与 Konard 的回答中的 t5 非常相似

选项 1 - 在您的开发计算机上安装 dotnet-t4

将其添加到您的 csproj 文件中。无需条件设置。

  <!-- T4 build support for .NET Core (Begin) -->

  <ItemGroup>
    <TextTemplate Include="**\*.tt" />
  </ItemGroup>

  <Target Name="TextTemplateTransform" BeforeTargets="BeforeBuild">
    <ItemGroup>
      <Compile Remove="**\*.cs" />
    </ItemGroup>
    <Exec WorkingDirectory="$(ProjectDir)" Command="t4 %(TextTemplate.Identity)" />
    <ItemGroup>
      <Compile Include="**\*.cs" />
    </ItemGroup>
  </Target>

  <!-- T4 build support for .NET Core (End) -->

选项 2 - 在您的开发机器上使用 VS 模板

如果您不希望每个人都在本地安装该工具,您仍然可以按照 Konard 的回答向项目添加条件构建步骤。请注意,Visual Studio 现在是 64 位,因此您可以使用

MSBuildExtensionsPath
代替
MSBuildExtensionsPath32
:

  <!-- T4 build support for .NET Core (Begin) -->

  <ItemGroup Condition="'$(MSBuildRuntimeType)'=='Core'">
    <TextTemplate Include="**\*.tt" />
  </ItemGroup>

  <Target Name="TextTemplateTransform" BeforeTargets="BeforeBuild" Condition="'$(MSBuildRuntimeType)'=='Core'">
    <ItemGroup>
      <Compile Remove="**\*.cs" />
    </ItemGroup>
    <Exec WorkingDirectory="$(ProjectDir)" Command="t4 %(TextTemplate.Identity)" />
    <ItemGroup>
      <Compile Include="**\*.cs" />
    </ItemGroup>
  </Target>

  <!-- T4 build support for .NET Core (End) -->

  <!-- T4 build support for Visual Studio (Begin) -->

  <PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Full'">
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
    <TransformOnBuild>true</TransformOnBuild>
    <!--Other properties can be inserted here--> 
    <!--Set to true to force overwriting of read-only output files, e.g. if they're not checked out (default is false)--> 
    <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
    <!--Set to false to transform files even if the output appears to be up-to-date (default is true)-->  
    <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
  </PropertyGroup>

  <Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" Condition="'$(MSBuildRuntimeType)'=='Full'" />

  <!-- T4 build support for Visual Studio (End) -->

0
投票

今天

msbuild
可以做到这一点,但 还没有
dotnet build

记录在这里

© www.soinside.com 2019 - 2024. All rights reserved.