内容简介:出于兼容性考虑,我们可能不再更新某个项目的 NuGet 包。典型的情况是软件版本进行了大规模的不兼容的升级,需要对旧格式的数据进行读取,以便迁移到新格式的数据。然而,团队开发的软件可能因为某个小伙伴不知道这样的历史问题,从而手抖将某个不应该更新的 NuGet 包更新了,于是迁移就挂了。本文提供了一种方法来避免某些特定 NuGet 包的升级。
出于兼容性考虑,我们可能不再更新某个项目的 NuGet 包。典型的情况是软件版本进行了大规模的不兼容的升级,需要对旧格式的数据进行读取,以便迁移到新格式的数据。
然而,团队开发的软件可能因为某个小伙伴不知道这样的历史问题,从而手抖将某个不应该更新的 NuGet 包更新了,于是迁移就挂了。
本文提供了一种方法来避免某些特定 NuGet 包的升级。
如果你只关心结果,请直接前往最后一节:终极解决方案
准备工作
本文提供的方法仅适用于使用了 Microsoft.NET.Sdk 的新 csproj 项目文件。(当然并不是说旧的 csproj 不能使用这种方法,只是写法上会有差别,我没有去研究如何编写。)
如果你的项目还在使用旧的 csproj 格式,推荐阅读 将 WPF、UWP 以及其他各种类型的旧 csproj 迁移成基于 Microsoft.NET.Sdk 的新 csproj 迁移成新格式之后再开始。
作为例子,假设我们的项目文件是这样的:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net47</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="LiteDB" Version="2.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> </ItemGroup> </Project>
LiteDB 是一个不应该被升级的 NuGet 包,但是最新版本已经是 4.1.4 了,很容易被团队中的其他小伙伴误升级。
▲ 当小伙伴打开包管理器的时候,会发现包版本不一致,然后就不小心升级了
思路
NuGet 使用 PackageReference
来管理所有的包引用,于是我试图通过隐藏 LiteDB 的 PackageReference
节点来达到目的。
而一个典型的隐藏方法便是使用 Target
。不在 Target
里面的属性和项是提前计算好的,而 Target
里面的属性和项是编译时才计算的。
可以通过阅读 如何编写基于 Microsoft.NET.Sdk 的跨平台的 MSBuild Target 了解更多 Target 的知识。
所以,我写了这样的 Target
,然后去掉前面的 PackageReference
。
<!-- 其实这种改法并没有作用,可谁知道呢! --> <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net47</TargetFramework> </PropertyGroup> <ItemGroup> <!-- 在这里把之前的 LiteDB 去掉了。 --> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> </ItemGroup> <!-- 这是新写的 Target,用来在编译期间引用 LiteDB。不过我不知道应该在什么时机执行。 --> <Target Name="ReferenceStaticLegacyPackage" BeforeTargets="???"> <ItemGroup> <PackageReference Include="LiteDB" Version="2.0.2" /> </ItemGroup> </Target> </Project>
还留了一个 BeforeTargets
没有填,因为并不知道应该填什么。于是我打开了 Microsoft.NET.Sdk
的文件夹 C:\Program Files\dotnet\sdk\2.1.300\Sdks
,试图寻找时机。
搜索 @(PackageReference)
发现有很多的 Target
都依赖于一个名为 CollectPackageReferences
的 Target
。
<Target Name="CollectResolvedSDKReferencesDesignTime" Returns="@(_ResolvedSDKReference)" DependsOnTargets="ResolveSDKReferencesDesignTime;CollectPackageReferences"> <!-- 省略 --> </Target>
从名称上可以猜测这是用来收集 PackageReference
的 Target
。
于是我可以将我们的 BeforeTargets
指定为 CollectPackageReferences
。
不过我发现在这种情况下,NuGet 包管理器的界面中能够发现这个项目使用了旧版本。并且在安装了新版本的包后,将因为多次引用不同版本而导致编译不通过。
所以,方案否决。
最终解决
既然无法阻止发现这个 NuGet 包,那思路就换成无论如何更新,都无效好了。
于是,通过 Remove
和重新 Include
固定版本来解决。
下面是项目的最终解决源码:
<!-- 其实这种改法并没有作用,可谁知道呢! --> <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net47</TargetFramework> </PropertyGroup> <ItemGroup> <!-- 无论这里版本填写多少,都不会有效。 --> <PackageReference Include="LiteDB" Version="4.1.4" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> </ItemGroup> <!-- 通过移除正常的引用并替换成固定版本的引用,达到无论如何更新都无法生效的目的。 --> <Target Name="ReferenceStaticLegacyPackage" BeforeTargets="CollectPackageReferences"> <ItemGroup> <PackageReference Remove="LiteDB" /> <PackageReference Include="LiteDB" Version="2.0.2" /> </ItemGroup> </Target> </Project>
在这种 Target
的帮助下,无论如何更新 LiteDB 的 NuGet 版本,都能更新成功,但无法生效。
本文会经常更新,请阅读原文: https://walterlv.github.io/post/prevent-nuget-package-upgrade.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://walterlv.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 芯片安全性升级 实现攻击前阻止 完美将黑客拒之门外
- 阻止恶意SSL通信六要点
- ios – 阻止递归和打破保留周期
- 如何阻止别人非法链接你网站的图片?
- vue拦截(阻止)浏览器后退事件
- 突破前端反调试:阻止页面不断 debugger
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。