在构建时将项目引用更改为NuGet包引用

13
我有一个Visual Studio解决方案,其中包含两个项目--一个.NET Standard(2.0)库,包含一些逻辑,一个.NET Framework(4.6.1)类库,包含用户界面等。然后将.NET Standard库添加为.NET Framework库的项目引用,以便它可以使用逻辑库中包含的方法。
然后,我在Azure DevOps中使用Azure Pipelines构建这两个项目,将它们打包为NuGet包,并将它们推送到由Azure Devops提供的NuGet服务器(Azure Artifacts)。
但是,当NuGet包发布时,它们只包括我通过NuGet添加到项目中的NuGet包的依赖关系。理想情况下,当我的.NET Standard(逻辑)库被打包并推送到NuGet服务器时,会向我的.NET Framework(UI)库添加一个对其的NuGet引用(带有更新的版本号等)。
是否有其他人遇到过这个问题,可以给我一些关于如何解决它的指导?我在网上看了看,但还没有结果。
谢谢!

你是如何打包 .net Framework 项目的?你是使用 .NuGet Pack 任务还是 MSBuild -t:Pack? - Josh Gust
如果你的 .net Framework 包引用了 .net Standard 项目作为项目引用,那么 .netSrd 项目的二进制文件应该包含在你的 .netFW 包的 /lib 目录中。 - Josh Gust
使用MSBuild条件,使项目可以同时引用两个参考。该条件可以针对环境变量或其他适当内容进行测试。然后,在任何计算机上,您都可以设置/重置变量以测试编译。 - Lex Li
@JoshGust 我正在使用 'nuget pack' 打包 .NET Framework 项目。目前为止,在构建服务器上我没有做任何更改将项目引用更改为包引用 - 看起来从迄今为止给出的回复中,这是我缺少的部分。 - Steven Day
@JoshGust 我也尝试在管道中的“nuget pack”构建步骤上使用“-IncludeReferencedProjects”开关来包含.NET Standard库,但是我收到错误消息“无法将类型为'System.String'的对象强制转换为类型'NuGet.Frameworks.NuGet.Frameworks1069249.NuGetFramework'。”当我尝试使用“nuget pack”打包.NET Standard库时,我遇到了类似的错误,但我通过改用“dotnet pack”解决了这个问题。看起来Nuget CLI不喜欢.NET Standard库。 - Steven Day
显示剩余6条评论
4个回答

7
我的回答分为两个部分。
首先,如果您使用的是 dotnet packmsbuild -t:pack 命令,而没有指定 nuspec 文件,则项目引用将自动成为 NuGet 依赖项。我使用以下命令进行了验证:
其次,如果您希望手动配置 NuGet 依赖项,可以在 nuspec 文件中添加 <dependencies> 元素,并列出所需的所有包。
dotnet new classlib -n ProjectA
dotnet new classlib -n ProjectB
dotnet add ProjectB/ProjectB.csproj reference ProjectA/ProjectA.csproj
dotnet pack ProjectB/ProjectB.csproj
ProjectB.1.0.0.nupkg依赖于ProjectA v1.0.0,对于SDK风格的项目可以"开箱即用",但是如果您有一个"旧风格"的项目(导入了Microsoft.CSharp.targets),则需要向NuGet.Build.Tasks.Pack添加包引用。如果使用PackageReference,则可能需要编辑csproj并将此依赖项设置为将PrivateAssets全部设置为所有内容,以避免此包成为nuget依赖项。如果您正在使用packages.config,或者它是否可能存在等价物我不确定。如果您正在使用msbuild或dotnet pack,但还有自己的nuspec文件,我建议避免这样做。您在nuspec中想要做的任何事情都应该通过在csproj中设置正确的属性或项属性来实现,并让pack目标自动生成nuspec。当您拥有自己的nuspec时,nuget的自动生成部分会被关闭,因此您可能会让自己的工作更加困难。
对于旧风格的csproj文件,我记得nuget会自动将项目引用转换为nuget依赖项,只要被引用的项目在与<project name>.csproj文件相同的目录中具有<project name>.nuspec文件(我几乎确定它在learn.microsoft.com/nuget上有文档)。但是,如果您的依赖项目是SDK风格项目(如.NET Core或.NET Standard项目所需),那么我已经建议不要在这些项目中使用nuspec文件,因此您真的应该考虑使用pack目标并停止使用nuget pack
我的回答的第二部分将直接回答您的问题,即如何在某些构建中使项目引用包引用。首先,您需要使用pack目标,可以通过使用SDK样式项目或引用NuGet.Build.Tasks.Pack包来实现。这样,您就不使用nuspec文件,一切都在您的csproj中定义,这只是一个MSBuild文件。 MSBuild具有条件,因此手动编辑您的csproj,并使您的项目引用具有某个条件,并使包引用具有相反的条件。我建议使用变量像$(CI),这样您可以使用msbuild -t: pack -p: CI = true 测试打包,并在CI机器上将CI设置为true作为环境变量。由于NuGet已经内置了将项目引用转换为nuget依赖项的功能,因此我建议使用它,而不是在包和项目引用之间切换,因此我不会给出如何执行此操作的复制粘贴示例。但是,如果这不是XY问题的情况,并且您确实需要这样做,则我已经提供了足够的指针,以便您可以自行解决其余部分。

2
NuGet CLI在不使用.nuspec文件时,会出现依赖项PackageReferences和项目引用的问题(仅当项目也是.net Core或.net Standard时?)。
使用dotnet packmsbuild -t:pack将项目引用包含为NuGet依赖项。这也解决了PackageReferences未被写入依赖项的问题。
假设您的.NET框架项目是从Visual Studio开箱即用的,则需要引用Nuget.Build.Tasks.Pack NuGet包才能访问必要的目标。我们在构建服务器上使用PowerShell将此数据写入.csproj文件,以便新的完整框架项目不会忘记它(我们正在努力避免创建这些项目)。正如@zivkan所提到的,您可能希望

将PrivateAssets设置为all,以避免此软件包成为NuGet依赖项

<PackageReference Include="NuGet.Build.Tasks.Pack">
  <PrivateAssets>all</PrivateAssets>
  <Version>4.8.0</Version>
</PackageReference>

0
在构建过程中将项目引用更改为NuGet包引用
很抱歉,在构建过程中无法将项目引用转换为NuGet包引用。这是因为它们是处理引用的两种不同方式。虽然现在有一些扩展可以将项目引用转换为NuGet包引用,但它们需要手动操作,我们无法在构建过程中使用它们。
请查看另一个线程以获取更多详细信息。
因此,我们无法在构建时将项目引用.NET Standard (2.0) library更改为NuGet包引用并添加到您的.NET Framework (UI)库中。
个人建议解决此问题,您可以在本地使用.net Standard (.netSrd)项目作为NuGet包引用,当您更新了.net Standard项目的版本号NuGet包时,您可以在Azure Artifacts中更新此包,并使用自定义NuGet任务命令调用nuget update命令,在构建.NET Framework (UI)库时将包更新到最新版本。

请查看以下详细信息:

在VSTS中构建后更新NuGet包至最新版本

希望这能有所帮助。


如果愿意在执行 NuGet 恢复和构建之前对 .csproj 文件进行更改,那么完全可以将项目引用替换为包引用。 - Josh Gust

0
如果您有一个ProjectReference,它将覆盖恢复图中与相同软件包ID的任何软件包引用。
来源:解决项目的软件包引用(dotnet github问题) 我自己尝试过(在csproj文件中添加了ProjectReference和PackageReference)。它可以成功构建,并且输出NuGet文件包含对其他NuGet软件包的依赖。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接