首页 > 解决方案 > 构建失败,因为找不到在构建时从 t4 转换的类型

问题描述

我有一个 ASP.NET Core 项目,它具有由 T4 模板生成的 IDataService 类型。如果我手动让Visual Studio生成对应的.cs文件,然后构建项目,一切正常:实现IDataService的各个类都能找到接口的类型,一切正常。

因为手动转换所有这些模板既乏味又容易出错(例如,在从源代码管理克隆解决方案之后),我修改了 .csproj 文件以在每次构建之前转换所有 t4 模板。这很有效:当我构建项目时,所有 T4 模板都会生成最新的 .cs 文件。

但是,当 IDataService.cs 尚不存在并且我构建项目时,我可以在构建输出中看到 IDataService.cs 正在创建(并且实际文件也出现在文件夹中),但随后构建失败,因为类型或找不到命名空间 IDataService。如果我然后重新运行构建,IDataService.cs 已经存在于以前的构建中,并且一切都构建得很好。

这里出了什么问题?为什么 msbuild 无法找到 IDataService.cs,尽管它是在那个构建上生成的?

这是构建输出(具有正常的详细程度):

Restoring NuGet packages...
To prevent NuGet from restoring packages during build, open the Visual Studio Options dialog, click on the NuGet Package Manager node and uncheck 'Allow NuGet to download missing packages during build.'
Committing restore...
Assets file has not changed. Skipping assets file writing. Path: C:\Users\Bar\source\repos\FooBar\Foo.WebApp\obj\project.assets.json
Restore completed in 246,75 ms for C:\Users\Bar\source\repos\FooBar\Foo.WebApp\Foo.WebApp.csproj.
1>------ Build started: Project: Foo.WebApp, Configuration: Debug Any CPU ------
1>Build started 20-10-2018 12:24:25.
1>Target TransformDuringBuild:
1>  Target ExecuteTransformations:
1>    Performing incremental T4 transformation
1>    Calculating whether transformed output is out of date...
1>    All outputs are up-to-date.
1>    Calculating whether transformed output is out of date...
1>    All outputs are up-to-date.
1>    Calculating whether transformed output is out of date...
1>    All outputs are up-to-date.
1>    Calculating whether transformed output is out of date...
1>    All outputs are up-to-date.
1>    Calculating whether transformed output is out of date...
1>    All outputs are up-to-date.
1>    Calculating whether transformed output is out of date...
1>    Transforming template Services\IDataService.tt...
1>    Performing incremental T4 preprocessing
1>Target _GetProjectReferenceTargetFrameworkProperties:
1>Target ResolveProjectReferences:
1>Target _HandlePackageFileConflicts:
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Immutable.dll' and 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.collections.immutable\1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll'.  NETSDK1036: Choosing 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Collections.Immutable.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Diagnostics.DiagnosticSource.dll' and 'Reference:C:\Users\Bar\.nuget\packages\system.diagnostics.diagnosticsource\4.5.1\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll'.  NETSDK1033: Choosing 'Reference:C:\Users\Bar\.nuget\packages\system.diagnostics.diagnosticsource\4.5.1\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll' because AssemblyVersion '4.0.3.1' is greater than '4.0.3.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.Parallel.dll' and 'Reference:C:\Users\Bar\.nuget\packages\system.linq.parallel\4.3.0\ref\netstandard1.1\System.Linq.Parallel.dll'.  NETSDK1033: Choosing 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Linq.Parallel.dll' because AssemblyVersion '4.0.3.0' is greater than '4.0.0.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Metadata.dll' and 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.reflection.metadata\1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll'.  NETSDK1036: Choosing 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Reflection.Metadata.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Xml.dll' and 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.runtime.serialization.xml\4.3.0\ref\netstandard1.3\System.Runtime.Serialization.Xml.dll'.  NETSDK1033: Choosing 'Reference:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1\System.Runtime.Serialization.Xml.dll' because AssemblyVersion '4.1.4.0' is greater than '4.1.1.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:Microsoft.Win32.Registry.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.win32.registry\4.5.0\lib\netstandard2.0\Microsoft.Win32.Registry.dll'.  NETSDK1036: Choosing 'Platform:Microsoft.Win32.Registry.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Collections.Immutable.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.collections.immutable\1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll'.  NETSDK1036: Choosing 'Platform:System.Collections.Immutable.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Diagnostics.DiagnosticSource.dll' and 'Runtime:C:\Users\Bar\.nuget\packages\system.diagnostics.diagnosticsource\4.5.1\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll'.  NETSDK1033: Choosing 'Runtime:C:\Users\Bar\.nuget\packages\system.diagnostics.diagnosticsource\4.5.1\lib\netstandard1.3\System.Diagnostics.DiagnosticSource.dll' because AssemblyVersion '4.0.3.1' is greater than '4.0.3.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Linq.Parallel.dll' and 'Runtime:C:\Users\Bar\.nuget\packages\system.linq.parallel\4.3.0\lib\netstandard1.3\System.Linq.Parallel.dll'.  NETSDK1033: Choosing 'Platform:System.Linq.Parallel.dll' because AssemblyVersion '4.0.3.0' is greater than '4.0.2.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Reflection.Metadata.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.reflection.metadata\1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll'.  NETSDK1036: Choosing 'Platform:System.Reflection.Metadata.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Runtime.Serialization.Xml.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.runtime.serialization.xml\4.3.0\lib\netstandard1.3\System.Runtime.Serialization.Xml.dll'.  NETSDK1033: Choosing 'Platform:System.Runtime.Serialization.Xml.dll' because AssemblyVersion '4.1.4.0' is greater than '4.1.2.0'.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.AccessControl.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.accesscontrol\4.5.0\lib\netstandard2.0\System.Security.AccessControl.dll'.  NETSDK1036: Choosing 'Platform:System.Security.AccessControl.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.Cryptography.Cng.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.cryptography.cng\4.5.0\lib\netcoreapp2.1\System.Security.Cryptography.Cng.dll'.  NETSDK1036: Choosing 'Platform:System.Security.Cryptography.Cng.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.Principal.Windows.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.principal.windows\4.5.0\lib\netstandard2.0\System.Security.Principal.Windows.dll'.  NETSDK1036: Choosing 'Platform:System.Security.Principal.Windows.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:Microsoft.Win32.Registry.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.win32.registry\4.5.0\runtimes\unix\lib\netstandard2.0\Microsoft.Win32.Registry.dll'.  NETSDK1036: Choosing 'Platform:Microsoft.Win32.Registry.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:Microsoft.Win32.Registry.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.win32.registry\4.5.0\runtimes\win\lib\netstandard2.0\Microsoft.Win32.Registry.dll'.  NETSDK1036: Choosing 'Platform:Microsoft.Win32.Registry.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.AccessControl.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.accesscontrol\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Security.AccessControl.dll'.  NETSDK1036: Choosing 'Platform:System.Security.AccessControl.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.Cryptography.Cng.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.cryptography.cng\4.5.0\runtimes\win\lib\netcoreapp2.1\System.Security.Cryptography.Cng.dll'.  NETSDK1036: Choosing 'Platform:System.Security.Cryptography.Cng.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.Principal.Windows.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.principal.windows\4.5.0\runtimes\unix\lib\netcoreapp2.0\System.Security.Principal.Windows.dll'.  NETSDK1036: Choosing 'Platform:System.Security.Principal.Windows.dll' because it comes from a package that is preferred.
1>  C:\Program Files\dotnet\sdk\2.1.403\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.ConflictResolution.targets(41,5): message NETSDK1041: Encountered conflict between 'Platform:System.Security.Principal.Windows.dll' and 'Runtime:C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.security.principal.windows\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Security.Principal.Windows.dll'.  NETSDK1036: Choosing 'Platform:System.Security.Principal.Windows.dll' because it comes from a package that is preferred.
1>Target GenerateTargetFrameworkMonikerAttribute:
1>  Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
1>Target _CoreGenerateRazorAssemblyInfo:
1>  Skipping target "_CoreGenerateRazorAssemblyInfo" because all output files are up-to-date with respect to the input files.
1>Target CoreGenerateAssemblyInfo:
1>  Skipping target "CoreGenerateAssemblyInfo" because all output files are up-to-date with respect to the input files.
1>Target CoreCompile:
1>  Using shared compilation with compiler from directory: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Roslyn
1>  Services\DiagramDataService.cs(19,47,19,59): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Services\TestDataService.cs(9,36,9,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\CharacterController.cs(22,36,22,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\CharacterController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\AuthorController.cs(22,33,22,45): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\AuthorController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\DiagramController.cs(22,34,22,46): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\StorylineController.cs(22,36,22,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\DiagramController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>  Controllers\GeneratedControllers\StorylineController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Done building target "CoreCompile" in project "Foo.WebApp.csproj" -- FAILED.
1>
1>Done building project "Foo.WebApp.csproj" -- FAILED.
1>
1>Build FAILED.
1>
1>Services\DiagramDataService.cs(19,47,19,59): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Services\TestDataService.cs(9,36,9,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\CharacterController.cs(22,36,22,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\CharacterController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\AuthorController.cs(22,33,22,45): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\AuthorController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\DiagramController.cs(22,34,22,46): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\StorylineController.cs(22,36,22,48): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\DiagramController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>Controllers\GeneratedControllers\StorylineController.cs(20,26,20,38): error CS0246: The type or namespace name 'IDataService' could not be found (are you missing a using directive or an assembly reference?)
1>    0 Warning(s)
1>    10 Error(s)
1>
1>Time Elapsed 00:00:12.29
========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========

这是 .csproj 文件:

<Project>
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk.Web" />

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
    <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
    <IsPackable>false</IsPackable>
    <SpaRoot>ClientApp\</SpaRoot>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>

    <!-- Set this to true if you enable server-side prerendering -->
    <BuildServerSideRenderer>false</BuildServerSideRenderer>
  </PropertyGroup>

  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>

  <ItemGroup>
    <T4ParameterValues Include="SolutionDir">
      <Value>$(SolutionDir)</Value>
      <Visible>False</Visible>
    </T4ParameterValues>
    <T4ParameterValues Include="Configuration">
      <Value>$(Configuration)</Value>
      <Visible>False</Visible>
    </T4ParameterValues>
  </ItemGroup>

  <PropertyGroup>
    <TransformOnBuild>true</TransformOnBuild>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="2.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.1" />
  </ItemGroup>

  <ItemGroup>
    <!-- Don't publish the SPA source files, but do show them in the project files list -->
    <Compile Remove="ClientApp\dist\**" />
    <Content Remove="$(SpaRoot)**" />
    <Content Remove="ClientApp\dist\**" />
    <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
  </ItemGroup>

  <ItemGroup>
    <EmbeddedResource Remove="ClientApp\dist\**" />
    <None Remove="ClientApp\dist\**" />
  </ItemGroup>

  <ItemGroup>
    <None Remove="ClientApp\src\app\diagram-types.ts" />
    <None Remove="foobar.db" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\Foo.WebApp.Database\Foo.WebApp.Database.csproj" />
    <ProjectReference Include="..\Foo\Foo.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
  </ItemGroup>

  <ItemGroup>
    <TypeScriptCompile Include="ClientApp\src\app\diagram-types.ts" />
  </ItemGroup>

  <ItemGroup>
    <None Update="Services\IDataService.tt">
      <Generator>TextTemplatingFileGenerator</Generator>
      <LastGenOutput>IDataService.cs</LastGenOutput>
    </None>
    <None Update="Services\DiagramDataService.tt">
      <Generator>TextTemplatingFileGenerator</Generator>
      <LastGenOutput>DiagramDataService.cs</LastGenOutput>
    </None>    
  </ItemGroup>


  <ItemGroup>
    <Compile Update="Services\IDataService.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>IDataService.tt</DependentUpon>
    </Compile>
    <Compile Update="Services\DiagramDataService.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>DiagramDataService.tt</DependentUpon>
    </Compile>    
  </ItemGroup>


  <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
    <!-- Ensure Node.js is installed -->
    <Exec Command="node --version" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
    <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
  </Target>

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --prod" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" />
      <DistFiles Include="$(SpaRoot)node_modules\**" Condition="'$(BuildServerSideRenderer)' == 'true'" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>%(DistFiles.Identity)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      </ResolvedFileToPublish>
    </ItemGroup> 

  </Target>

  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.Web" />
  <Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" />
</Project>

标签: visual-studiomsbuild.net-coret4

解决方案


我已经设法让它工作了,但我不太清楚为什么。我假设 msbuild 收集要构建的文件,然后转换 t4 模板,然后编译它收集的文件,因此不包括作为 T4 转换的一部分生成的文件。

项目文件为每个生成的文件列出了一个 <Compile> 元素,文件名位于“更新”属性中。将该属性更改为“包含”将导致文件包含在构建中,但这引入了一个新问题:如果文件尚不存在,则构建将起作用,但在后续构建中,文件将被隐式包含MSBuild 由于位于项目目录中,通过项目文件明确显示,导致构建错误。

我现在对这些元素中的每一个都使用了 Condition 属性来检查文件是否已经存在:如果存在,则不会包含该文件(因为 msbuild 已经隐式执行了该操作),如果不存在,它将被包括在内(因为 msbuild 不会知道它)。这是生成的 .csproj 文件:

<Project>
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk.Web" />

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
    <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
    <IsPackable>false</IsPackable>
    <SpaRoot>ClientApp\</SpaRoot>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>

    <!-- Set this to true if you enable server-side prerendering -->
    <BuildServerSideRenderer>false</BuildServerSideRenderer>
  </PropertyGroup>

  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>

  <ItemGroup>
    <T4ParameterValues Include="SolutionDir">
      <Value>$(SolutionDir)</Value>
      <Visible>False</Visible>
    </T4ParameterValues>
    <T4ParameterValues Include="Configuration">
      <Value>$(Configuration)</Value>
      <Visible>False</Visible>
    </T4ParameterValues>
  </ItemGroup>

  <PropertyGroup>
    <TransformOnBuild>true</TransformOnBuild>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="2.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.1" />
  </ItemGroup>

  <ItemGroup>
    <!-- Don't publish the SPA source files, but do show them in the project files list -->
    <Compile Remove="ClientApp\dist\**" />
    <Content Remove="$(SpaRoot)**" />
    <Content Remove="ClientApp\dist\**" />
    <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
  </ItemGroup>

  <ItemGroup>
    <EmbeddedResource Remove="ClientApp\dist\**" />
    <None Remove="ClientApp\dist\**" />
  </ItemGroup>

  <ItemGroup>
    <None Remove="ClientApp\src\app\diagram-types.ts" />
    <None Remove="foobar.db" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\Foo.WebApp.Database\Foo.WebApp.Database.csproj" />
    <ProjectReference Include="..\Foo\Foo.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
  </ItemGroup>

  <ItemGroup>
    <TypeScriptCompile Include="ClientApp\src\app\diagram-types.ts" />
  </ItemGroup>

  <ItemGroup>
    <None Update="Services\IDataService.tt">
      <Generator>TextTemplatingFileGenerator</Generator>
      <LastGenOutput>IDataService.cs</LastGenOutput>
    </None>
    <None Update="Services\DiagramDataService.tt">
      <Generator>TextTemplatingFileGenerator</Generator>
      <LastGenOutput>DiagramDataService.cs</LastGenOutput>
    </None>    
  </ItemGroup>


  <ItemGroup>
    <Compile Condition="!Exists('Services\IDataService.cs')" Include="Services\IDataService.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>IDataService.tt</DependentUpon>
    </Compile>
    <Compile Condition="!Exists('Services\DiagramDataService.cs')" Include="Services\DiagramDataService.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>DiagramDataService.tt</DependentUpon>
    </Compile>    
  </ItemGroup>


  <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
    <!-- Ensure Node.js is installed -->
    <Exec Command="node --version" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
    <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
  </Target>

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --prod" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" />
      <DistFiles Include="$(SpaRoot)node_modules\**" Condition="'$(BuildServerSideRenderer)' == 'true'" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>%(DistFiles.Identity)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      </ResolvedFileToPublish>
    </ItemGroup> 

  </Target>

  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.Web" />
  <Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" />
</Project>

现在我可以根据需要从 Git 克隆项目、构建和重建,所有内容都会自动生成并包含在构建中。


推荐阅读