使用 Directory.Build.Props 更改 .NetFramework 项目上的 TargetFrameworkVersion 意外影响 .NetStandard 项目

Using Directory.Build.Props to change TargetFrameworkVersion on .NetFramework projects affects .NetStandard projects unexpectedly

我正在尝试使用 Directory.Build.props 文件将一堆项目的 TargetFrameworkVersion 从 v4.6.1 更改为 v4.8。
我在 Directory.Build.props 文件下组合了 .net 框架和 .net 标准项目,我想在更新时忽略 .net 标准项目。
对于 .net 框架项目,一切都按预期工作但是,条件 "'$(TargetFramework.Contains(netstandard))' == 'false'",做相反的事情!对于 .net 标准。
换句话说,为该项目添加了 属性 并且构建失败,而它不应该。

MyClassLibrary.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>
</Project>

Directory.Build.props

<?xml version="1.0" encoding="utf-8"?>
<Project>
    <PropertyGroup Condition="'$(TargetFramework.Contains(netstandard))' == 'false'">
        <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    </PropertyGroup>
</Project>

怎么会错呢?

正如this document所说,Directory.Build.props是在MSBuild的早期导入的,这意味着它会先执行文件的内容,然后再从xxx.csproj文件中读取所有属性你的项目。

Directory.Build.targets是在xxx.csproj文件末尾导入的,所以可以覆盖属性。

Directory.Build.props通常用于创建全局属性,而Directory.Build.targets用于覆盖属性。

============================================= =============================

对于 Net Framework 项目,

在你的问题中,MSBuild首先读取Directory.Build.props中的属性TargetFrameworkVersion 4.8并且这是真的。

属性 TargetFrameworknet framework 项目中不存在(它是一个 属性 用于新的 sdk 项目 ), 所以值为, 条件总是flase 所以条件成立.(flase=false).

然后,MSBuild读取xxx.csproj,它会读取属性TargetFrameworkVersion 4.6.1然后覆盖属性4.8。所以它将始终使用值 4.6.1.

============================================= =============================

对于 Net Standard 项目,属性 TargetFrameworkxxx.csproj 文件下定义。而当你第一次阅读内容并在Directory.Build.props文件中使用它时。

因为文件在读取xxx.csproj之前运行,所以TargetFramework属性还没有定义,所以条件是falsefalse=false引出条件成立。它将读取 属性 TargetFrameworkVersion 4.8 而网络标准项目使用 属性 TargetFramework.

TargetFrameworkVersion设置为net framework 4.8,而在net标准项目中,该值通常为v2.0v2.1net standard 2.0net standard 2.1), 它无法将 net framework 4.8 读入网络标准项目。而后面的xxx.csproj文件没有值覆盖TargetFrameworkVersion为正常的net standard

因此 TargetFrameworkVersion 作为 net framework 的值嵌入到 net standard 项目中,因此构建因不兼容而失败。

解决方案

而不是,您应该将 Directory.Build.props 文件重命名为 Directory.Build.targets.

然后,重新启动您的项目,重建您的解决方案以启用它。而且在我这边也能很好地发挥作用。

注意:尽管您右键单击项目 Properties-->Application-- >Target Framework 显示旧的 net framework 4.6.1MSBuild 已将其设置为 net48

只是UI显示问题,没关系,可以忽略。