内容简介:出于兼容性考虑,我们可能不再更新某个项目的 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
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Black Box Society
Frank Pasquale / Harvard University Press / 2015-1-5 / USD 35.00
Every day, corporations are connecting the dots about our personal behavior—silently scrutinizing clues left behind by our work habits and Internet use. The data compiled and portraits created are inc......一起来看看 《The Black Box Society》 这本书的介绍吧!