![](/img/trans.png)
[英]Nuget Conflicting projectreference and packagereference
[英]NuGet Versioning with ProjectReference Dependencies
我有一個包含多個項目的解決方案。 假設PackageA和PackageB ,其中PackageB依賴於帶有ProjectReference的PackageA 。
每個項目都設置為在構建時還輸出一個 NuGet 包。 此過程本身運行良好,但我無法為單個構建指定包版本范圍。 例如,我想限制 PackageB 僅引用 PackageA 版本 1.0.*(補丁步驟)。
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup
<TargetFrameworks>netstandard2.0;netcoreapp2.0;net46</TargetFrameworks>
<RootNamespace>PackageB</RootNamespace>
<Company>MyCompany</Company>
<Authors>John Doe</Authors>
<Description>This package depends on a specific version of PackageA.</Description>
<Version>1.1.0</Version>
<Copyright>Copyright © 2018 John Doe</Copyright>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\PackageA\PackageA.csproj" />
</ItemGroup>
</Project>
MSBuild 似乎忽略了ProjectReference標記中的任何Version="1.0.*"或AllowVersion="1.0.*"參數。
是否有可能在不破壞ProjectReference或使用PackageReference的情況下指定版本范圍?
好吧,讓我們想想我們可以通過嗎? 該項目可能在其中某個位置嵌入了版本號,但它可能是最新版本或以前的版本,甚至可能沒有構建,也無法保證后續的構建步驟不會更新該值。 構建系統生成版本化工件的時間點接近構建的結尾,通常是最后一步,通常是打包或發布步驟。
如果您的項目必須限制其任何依賴項的版本范圍,則它應該依賴於其他軟件包,而不是構建它們的項目。 這提供了自然的異步工作流集,以饋入單個產品。
如果您希望將依賴項構建到最新,則必須使所有項目彼此兼容並保持兼容性。 項目依賴項實際上僅對開發人員構建有意義,而對CI構建則沒有意義。
您不應該做的一件事,就是生產兩個具有相同版本號的不同軟件包。 Visual Studio項目在版本控制方面被設計破壞,因為它們默認使用必須在構建之前設置的靜態版本字符串。 如果您碰巧忘記增加該數字,則會違反此語義版本控制規則。
即使Nuget / VS開發人員能夠滿足您的要求,但這也不是一個好的解決方案。 如果當前簽出的項目的版本超出指定范圍怎么辦? 假設開發人員可以弄清楚要檢查版本控制的哪些代碼,那真的是您想在開發人員框中發生的事情嗎? 他們提出的任何解決方案都會很復雜,而且容易出錯。 即使您已經簽出了該版本,Nuget也不知道您沒有對其進行重大更改。
最好只使用已發布的程序包作為依賴項來運行獨立的代碼管道,進行審查,構建,打包, 測試和發布。
不,沒有辦法通過該項目的版本屬性來限制項目引用。
如果您希望您的依賴包獨立於其依賴項而變化並限制它將依賴的更改范圍,那么您非常需要使用包引用而不是項目引用(是的,即使這些項目在同一個解決方案)。
當您引用一個項目時,您是在向您的 IDE 聲明,您希望將引用的項目設計時狀態包含在您的依賴項目設計時狀態中,以便您可以在構建之前使用它並在 IDE 中查看對它的更改. 當你的依賴項目被構建時,它的依賴也會被構建。 因此,項目參考始終是最新版本的參考。 您不能引用項目的先前版本,但可以引用先前構建的項目的版本化結果。
我不確定為什么這是這個決定,但是當您使用項目引用打包一個依賴於另一個項目的項目時, dotnet pack
和nuget
似乎假設您還將將這些項目中的每一個打包為包同樣,並將項目引用轉換為與依賴項目包相同版本的包的包引用。 因此,如果您打包projB @ v1.2.3
包將具有對projA @ v1.2.3
的依賴項引用。 如果您不打包projA @ v1.2.3
或者您不發布該軟件包(因為可能沒有對其進行任何更改), projB @ v1.2.3
的消費者將無法安裝,因為 nuget 找不到projA @ v1.2.3
。 因此,如果您要堅持對包使用項目引用,那么那些被引用的項目也應該是與它們的主機版本控制的包(無論它們是否更改)。
您的問題是基於 NodeJS 版本控制的工作原理( ^
和~
)嗎? 在 .NET 中這是不可能的,也沒有必要。
NodeJS 需要這個,因為你知道,它是 javascript。 由於 javascript 沒有嚴格的類型檢查,因此您需要某種方式來驗證包是否相互兼容。 某些屬性、方法可能存在也可能不存在於某些對象上。 因此,構建系統(節點)可以驗證這一點的唯一方法是通過包版本選擇器。
正如我所說,在 .NET 中我們不需要這個,因為它是一種嚴格的編程語言。 如果類中不存在字段、屬性或方法,則項目根本不會構建。
現有的 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>
給定在其他項目中指定的包版本,例如
<!-- ..\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>
生成的 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>
這個有用的目標可以放入 Directory.Build.targets 以涵蓋解決方案中的所有項目。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.