具有 ProjectReference 依赖项的 NuGet 版本控制

Aeo*_*eon 11 c# nuget semantic-versioning

我有一个包含多个项目的解决方案。假设PackageAPackageB,其中PackageB依赖于带有ProjectReference 的PackageA。\n每个项目都设置为在构建时输出 NuGet 包。这个过程本身工作得很好,但我无法为各个构建指定包版本范围。\n例如 我想限制 PackageB 仅引用 PackageA 版本 1.0.* (补丁步骤)。

\n\n
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">\n  <PropertyGroup\n    <TargetFrameworks>netstandard2.0;netcoreapp2.0;net46</TargetFrameworks>\n\n    <RootNamespace>PackageB</RootNamespace>\n    <Company>MyCompany</Company>\n    <Authors>John Doe</Authors>\n    <Description>This package depends on a specific version of PackageA.</Description>\n    <Version>1.1.0</Version>\n    <Copyright>Copyright \xc2\xa9 2018 John Doe</Copyright>\n    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include="..\\PackageA\\PackageA.csproj" />\n  </ItemGroup>\n</Project>\n
Run Code Online (Sandbox Code Playgroud)\n\n

MSBuild 似乎忽略ProjectReference标记中的任何Version="1.0.*"AllowVersion="1.0.*"参数。\n是否可以在不破坏ProjectReference或使用PackageReference 的情况下指定版本范围?

\n

Jos*_*ust 9

简答

不,无法通过项目的版本属性来限制项目引用。

更长的答案

如果您希望依赖包独立于其依赖关系而变化,并限制其依赖的更改范围,那么您非常需要使用包引用而不是项目引用(是的,即使这些项目位于同一个项目中)解决方案)。

立即项目参考

当您引用一个项目时,您正在向 IDE 做出声明,表明您希望将引用的项目设计时状态包含在依赖项目设计时状态中,以便您可以使用它并在构建之前在 IDE 中查看对其所做的更改。当您的依赖项目构建时,它的依赖项也会构建。因此,项目参考始终是最新版本的参考。您无法引用项目的先前版本,但可以引用先前构建的项目的版本化结果。

打包项目参考

根据构建依赖项目时构建的项目引用,当您使用项目引用打包依赖于另一个项目的项目时,dotnet packnuget pack假设您也将把每个项目打包为包,并将项目引用作为包依赖项写入依赖项目包的同一版本中。因此,如果您打包projB @ v1.2.3该包,将会有一个对projA @ v1.2.3. 如果您不打包projA @ v1.2.3或不发布该包(因为可能没有对其进行任何更改),则使用者projB @ v1.2.3将安装失败,因为 nuget 找不到projA @ v1.2.3. 如果您坚持使用包的项目引用,那么这些引用的项目也应该是与其主机一起进行版本控制的包(无论它们是否更改)。

上述参考规则的一个小例外

作为与主机版本相同的包依赖项列出的项目引用的例外是其资产标记为私有的项目引用。在这些情况下,您要么需要创建一个将这些资产包含在包中的构建目标,要么制定一些其他约定来将依赖项传递给运行时。使用私有资产路径不允许您执行您所要求的操作,但它是项目引用成为包的列出依赖项的规则的例外。


Ant*_*hyy 6

现有的 NuGet 目标不直接支持这一点。GitHub 上请求此功能的几个问题 ( 1 , 2 ) 已开放多年。然而,通过一些 MSBuild 项目技巧,我能够 ProjectReference使用两个属性进行“扩展”,PackageVersion并且ExactVersion

<!-- MyProject.csproj -->
<Project Sdk="Microsoft.NET.Sdk" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <ItemGroup>
    <ProjectReference Include="..\MyProject1\MyProject1.csproj" PackageVersion="[1.1.0, 2.0.0)" />
    <ProjectReference Include="..\MyProject2\MyProject2.csproj" ExactVersion="true" />
    <ProjectReference Include="..\MyProject3\MyProject3.csproj" />
  </ItemGroup>
  ...
  <Target Name="UseExplicitPackageVersions" BeforeTargets="GenerateNuspec">
    <ItemGroup>
      <_ProjectReferenceWithExplicitPackageVersion Include="@(ProjectReference->'%(FullPath)')"
        Condition="'%(ProjectReference.PackageVersion)' != ''" />
      <_ProjectReferenceWithExactPackageVersion Include="@(ProjectReference->'%(FullPath)')"
        Condition="'%(ProjectReference.ExactVersion)' == 'true'" />
      <_ProjectReferenceWithReassignedVersion Include="@(_ProjectReferencesWithVersions)"
        Condition="'%(Identity)' != '' And '@(_ProjectReferencesWithVersions)' == '@(_ProjectReferenceWithExplicitPackageVersion)'">
        <ProjectVersion>@(_ProjectReferenceWithExplicitPackageVersion->'%(PackageVersion)')</ProjectVersion>
      </_ProjectReferenceWithReassignedVersion>
      <_ProjectReferenceWithReassignedVersion Include="@(_ProjectReferencesWithVersions)"
        Condition="'%(Identity)' != '' And '@(_ProjectReferencesWithVersions)' == '@(_ProjectReferenceWithExactPackageVersion)'">
        <ProjectVersion>[@(_ProjectReferencesWithVersions->'%(ProjectVersion)')]</ProjectVersion>
      </_ProjectReferenceWithReassignedVersion>
      <_ProjectReferencesWithVersions Remove="@(_ProjectReferenceWithReassignedVersion)" />
      <_ProjectReferencesWithVersions Include="@(_ProjectReferenceWithReassignedVersion)" />
    </ItemGroup>
  </Target>
  ...
</Project>
Run Code Online (Sandbox Code Playgroud)

给定其他项目中指定的包版本,如下所示

<!-- ..\MyProject1\MyProject1.csproj -->
<!-- ..\MyProject2\MyProject2.csproj -->
<!-- ..\MyProject3\MyProject3.csproj -->
<Project Sdk="Microsoft.NET.Sdk" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Version>1.1.3</Version>
  </PropertyGroup>
  ...
</Project>
Run Code Online (Sandbox Code Playgroud)

生成的 MyProject.nuspec 文件将包含以下依赖项:

<?xml version="1.0" encoding="utf-8" ?>
<package>
  <metadata>
    <dependencies>
      <group targetFramework="...">
        <dependency id="MyProject1" version="[1.1.0, 2.0.0)" />
        <dependency id="MyProject2" version="[1.1.3]" />
        <dependency id="MyProject3" version="1.1.3" />
      </group>
    </dependencies>
  </metadata>
</package>
Run Code Online (Sandbox Code Playgroud)

这个有用的目标可以放入 Directory.Build.targets 中以覆盖解决方案中的所有项目。


小智 1

据我所知这是不可能的ProjectReference,但是 Github 上这个主题有一些未解决的问题,所以他们可能会在某个时候实现它。

但目前此功能仅在PackageReference. 文档