基于.Net TargetFramework的MSBuild Conditional PackageReference

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

简介

我正在构建一个类库,可供一些针对 .Net Framework 4.0 的旧应用程序和针对 .Net Framework 4.6.1 的新应用程序使用

我正在类库中添加一些需要 .Net Framework 4.6.1 的数据库/Hibernate 新代码。此新代码与 .Net Framework 4.0 不兼容,因为 nuGet 包 FluentNHibernate 3.1.0 需要 .Net Framework 4.6.1 及更高版本。而遗留应用程序不需要此功能。

我想要实现什么

我正在尝试有条件地构建类库,以便可以使用一个代码库和主 git 分支来构建与一个或另一个应用程序兼容的版本。

到目前为止,我已经能够:

  • 定义一个常量,表示目标框架(FWK40)
    • 用于在 .cs 代码中调整代码以适应目标框架
  • 有条件地定义目标框架(TargetFrameworkVersion)
  • 不在正确的 TargetFrameworkVersion 下时从构建中排除文件

这是

.CSPROJ
目前的样子(重点是相关调整):

<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug.Net40|AnyCPU'">

    <!-- Set target framework here -->

    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\Debug.Net40\</OutputPath>

    <!-- Define Build-time constant here -->

    <DefineConstants Condition=" '$(TargetFrameworkVersion)' == 'v4.0'" >FWK40</DefineConstants>

 </PropertyGroup>

 <ItemGroup>

    <-- Conditionally include .cs files here -->

    <Compile Include="Database\GeneralSQL.cs" Condition="'$(TargetFrameworkVersion)' != 'v4.0'" />
    <Compile Include="Database\NamingStrategy.cs" Condition="'$(TargetFrameworkVersion)' != 'v4.0'" />
 <ItemGroup>

 <ItemGroup>

    <-- In THEORY conditionally include PackageReference here -->

    <PackageReference Include="FluentNHibernate" Condition="'$(TargetFramework)' != 'net40'" >
        <Version>3.1.0</Version>
    </PackageReference>
 </ItemGroup>

目前的结果

发生了什么,我收到一个 nuGet 错误:

NU1202:FluentNHibernate 3.1.0 软件包与 net40(.NETFramework,版本=v4.0)不兼容。 FluentNHibernate 3.1.0 包支持: 无法恢复 C:_projets epos\TestSolution\TestLibrary\TestLibrary.csproj(19 毫秒内)。
NuGet 包恢复失败。请参阅错误列表窗口以了解详细的警告和错误。

尽管存在此错误,所有程序集、DLL 类库本身以及使用该类库的 EXE 控制台应用程序都正确生成了AND,到目前为止它们运行正常。

问题

我无法有条件地包含 nuGet a

PackageReference

并且 nuGet 错误仍然会导致 MSBuild.exe 失败,从而阻止 CI/CD 管道正常工作..

我已经尝试过

我尝试了很多方法来摆脱 nuget NU1202 错误消息。

#1 我最初尝试过基于 $(TargetFrameworkVersion) 的其他条件,该条件在整个

.csproj
中都有效,但无济于事。

#2 根据官方文档,nuGet

ReferencePackage
仅支持基于 $(TargetFramework) adding-a-packagereference-condition 的条件,如上面的示例 .csproj 所示。但这仍然行不通。

  • 到目前为止我还无法弄清楚该属性

    TargetFramework
    到底是什么样子。我在详细级别诊断中运行了 MSBUILD.EXE,它转储了所有属性,但 TargetFramework 未列出(而其他则列出)

  • 我尝试“反转”条件

    == 'net461'
    ,这样如果预期值不正确,则不会包含该值,并且错误将消失=>没有效果,错误仍然存在

#3 我尝试为自己定义 TargetFramework 属性

<!-- Set target framework here -->
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFramework>net40</TargetFramework>
  • 结果会更糟!
  • Visual Studio 不喜欢它,“配置管理器”坏了
    • 它不允许为项目设置特定的配置。
    • 从 Debug.Net40 更改为任何其他配置(或加载项目)都会显示一条令人讨厌的错误消息
Current solution contains incorrect configuration mappings. It may cause projects to not work properly

csproj 肯定也没有正确加载,项目将跳过构建步骤。

我现在在哪里

我真的被困住了!似乎无法找到一种方法来完成这项工作。

  • 我不想拥有一个分支 master40 和一个分支 master 来处理这个问题。
  • 我不想拥有两个不同的 csproj 文件,除非我能以某种方式设法共享/包含一个文件到另一个文件中并且 Visual Studio 不会抱怨

真正正确的事情是使 ReferencePackage 上的条件真正按预期工作。

c# msbuild packagereference
1个回答
0
投票

您想要的是多目标。 您链接的文档似乎仅适用于 SDK 样式的项目。 AFAIK,传统风格的项目格式不支持多目标。

我建议迁移到SDK 风格的项目格式。 那里很多事情都简单得多,更不用说有更好的记录了。 您可以使用工具来执行此操作,例如 hvanbakel/CsprojToVs2017dotnet/try-convert。不要被它的名称和术语的错误用法所愚弄。 (因为这也一直在 SO 上混淆:是的,您可以将 SDK 样式格式与 .NET Framework TFM 一起使用;SDK 样式与 TFM 或 Visual Studio 版本无关,但仅与所需的最低 MSBuild 有关版本)。

为特定项目完成此操作后,适用于多目标的文档,并且您可以在

Condition
上使用
$(TargetFramework)
,就像您已经在
PackageReference
Compile
项目中所做的那样团体以及几乎任何您想要的地方。

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