首页 > 其他分享 >.NET 高效开发Nuget管理工具(开源)

.NET 高效开发Nuget管理工具(开源)

时间:2024-08-16 21:27:16浏览次数:13  
标签:csproj 管理工具 Nuget 版本 解决方案 var NET 源代码

我们.NET开发会引用很多外部Nuget包,多项目、多个解决方案、甚至多个仓库。

简单的Nuget包管理,通过VS就能比较简单处理好。但复杂的场景呢,比如:

1.一个仓库里,有多个解决方案的Nuget包管理 -- 我现在项目就是这样的,针对会议大屏的全家桶软件集代码仓库。这个仓库里,接近30个工具/应用软件:

2. 多个仓库,多个解决方案、多个项目的Nuget管理 --  公司产品项目业务比较复杂,抽了很多组件(目前有53个),组件间需要处理好版本冲突,以及因版本依赖需要递增升级自己的版本号

这些复杂场景会给开发同学带来操作管理代码的低效问题

所以如何高效处理好项目之间的Nuget版本冲突,如何快速升级Nuget版本,如何解决多项目对Nuget组件源码的快速调试,下面我们分别介绍下

Nuget版本统一、版本升级

项目Csproj引用Nuget包,管理多个项目的解决方案,通过VS的Nuget管理页面以及CsProj文件编辑能解决大部分情况下的Nuget版本操作。

稍复杂的仓库内多解决方案场景,经MVP德熙大佬 lindexi - 博客园 (cnblogs.com) 的提醒,中央包管理即Packages.props文件也能可以管理一个仓库内的Nuget包,中央包管理 | Microsoft Learn。Packages.props统一配置好仓库内公共的Nuget包版本,然后Csproj根据需要引用相应的Nuget包

1 <Project Sdk="Microsoft.NET.Sdk">
2   <PropertyGroup>
3     <TargetFramework>net6.0</TargetFramework>
4   </PropertyGroup>
5   <ItemGroup>
6     <PackageReference Include="Newtonsoft.Json" />
7   </ItemGroup>
8 </Project>

但是,其实我个人不推荐。如果新增了一个Nuget引用DirectShowLib,VS又会默认在CSproj文件内添加版本号,未自动归纳到Package.props内:

需要按中央包管理路径,去解决方案或者仓库下Packages.props添加Nuget版本信息。此方案有一定的修改成本,个人也觉得项目的Nuget引用版本号不够显眼、阅读性会减弱

继续用csproj管理Nuget包,多项目之间的管理成本我们用工具解决: WindowsOrg/NugetEfficientTool: VisualStudio项目开发-Nuget操作效率工具 (github.com)

下图是使用Nuget版本工具,对全家桶应用集所在的文件夹进行Nuget版本检测:

按上图界面操作:
1. 项目路径,输入仓库代码所在的目录(也可以外层目录)、解决方案sln文件路径

2. 点击“开始检测”,会显示Nuget待修复信息。如上图,H3C.Setting.Camera存在很多csproj文件内版本是一致的,但与Nuget源最新版本不一致,需要升级

3. 点击“修复版本冲突”,弹出版本选择窗口,选择相应版本执行修复。执行后,csproj都会同步H3C.Setting.Camera版本为1.1.15

选择版本时,可以全选也可以指定Nuget同步版本号。

Nuget版本工具,是基于小伙伴博哥工具版本dotnet-campus/dotnetCampus.NugetMergeFixTool (github.com)优化改良的。工具目前已经实现的功能:

1. 同步一个解决方案下Nuget版本

2. 同步一个文件夹下多解决方案的Nuget版本
3. 支持设置Nuget源,同步升级Nuget版本(上方截图就是这个场景)

Nuget版本同步的原理,是获取路径下的所有csproj文件,解析出引用Nuget的PackageReference信息-Nuget名称、版本号。列出这些版本不同的Nuget,让开发人员选择需要降级或者升级的版本号,然后再次修改保存csproj文件的Nuget引用版本号。

获取一个csproj文档内所有PackageReference节点:

 1     /// <summary>
 2     /// 获取PackageReference名称对应的节点
 3     /// </summary>
 4     /// <param name="xDocument"></param>
 5     /// <returns></returns>
 6     private List<XElement> GetPackageReferenceElements(XDocument xDocument)
 7     {
 8         if (xDocument == null)
 9         {
10             throw new ArgumentNullException(nameof(xDocument));
11         }
12         var xElementList = new List<XElement>();
13         var itemGroupElements = xDocument.Root.Elements().Where(x => x.Name.LocalName == "ItemGroup");
14         foreach (var itemGroupElement in itemGroupElements)
15         {
16             xElementList.AddRange(itemGroupElement.Elements().Where(x => x.Name.LocalName == "PackageReference"));
17         }
18         return xElementList;
19     }

另外,针对多个仓库多个解决方案的组件集版本号同步场景,下面介绍下53个组件仓库70多个Nuget包是如何一键解决Nuget之间版本依赖的问题。Nuget版本工具结合Jenkins做了个版本号自动构建:

1. 组件集工作组下的所有组件仓库clone到本地,并行编译多个解决方案

2. 后台执行Nuget版本工具,csproj文件中Nuget自动升级到最高版本。同时csproj文件如有引用变更,则当前组件自身版本号新增一位构建号

3. 循环第2步,直到所有csproj文件内相同Nuget包的版本均一致

4. 保存归档Nuget包至服务器,Git Push所有组件仓库对csproj文件的变更

下图是Jenkins某次一键同步Nuget包版本的流程日志:

有需要的可以直接下载Nuget工具:Nuget工具_1.0.3.1012.exe,以命令行参数执行、一键升级目录下的所有组件版本号:NugetEfficientTool.exe D:\Gitlab-Company\Components

Nuget源代码替换

开发应用,遇到需要调试内部的Nuget源代码,一般我们是卸载Nuget包、然后引用源组件项目csproj。

这样操作,1-2个项目操作还好,遇上几十个项目需要替换Nuget源项目代码,效率就很低了

简单重复的事情,都要通过工具来简化,这里也是Nuget工具操作:

1. 项目路径,输入仓库代码所在的目录(也可以是多仓库目录),或者仓库解决方案.sln文件路径

2. 输入Nuget包H3C.Family.App对应的源代码csproj文件路径,或者csproj所在目录。输入后,会自动填充Nuget名称H3C.Family.App

3. 点击“替换”,替换所有csproj项目内H3C.Family.App的Nuget引用PackageReference,为H3C.Family.App的项目引用ProjectReference,就可以开始源代码调试了

代码调试完,可以点击“还原”,撤回Nuget源代码的替换。然后Nuget源代码可以提交代码、归档Nuget包给上层应用使用了。

是不是很方便呢?这里Nuget替换,目前版本支持:

1. 一个解决方案,对多个Nuget源的替换

2. 目录即多个解决方案,对多个Nuget源的替换

3. 支持多个相互之间依赖的Nuget包替换(自动识别依赖)和还原

支持目录下的Nuget替换,极大提升了多项目多仓库协同开发的效率,见某次的操作:

我所在项目是智能交互大屏会议场景的会议软件集(全家桶),应用软件太多了。有时候修复一个摄像头组件的BUG,人工操作的话需要打开每个解决方案、替换源代码,太浪费时间。

而通过Nuget工具一键替换所有的Nuget源代码,然后用VS解决方案管理器切换视图,可极快的打开项目进行源代码确认、调试,效率提升相差一个量级

这里的Nuget替换,最初始版本是小伙伴俊杰同学 J.晒太阳的猫 - 博客园 (cnblogs.com) 开发的,初始版本是在VS内以扩展工具来运行。可惜我没有他的源代码,就按个人需求另外开发了一套exe的Nuget工具版本。

其中主要逻辑,
1. 解决方案,新增Nuget名称项目:

 1     var solutionFileLines = File.ReadAllLines(_solutionFile).ToList();
 2     //添加Project
 3     var previousProjectIndex = solutionFileLines.FindLastIndex(i => i.Contains(StartProjectRex));
 4     var previousProjectLine = solutionFileLines[previousProjectIndex];
 5     var solutionId = previousProjectLine.Replace(StartProjectRex, string.Empty).Substring(0, GuidLength);
 6     var newProjectLine = $"{StartProjectRex}{solutionId}}}\") = \"{_nugetName}\", \"{_sourceProjectFile}\", \"{{{_newProjectId}}}\"";
 7     solutionFileLines.Insert(previousProjectIndex + 2, "EndProject");
 8     solutionFileLines.Insert(previousProjectIndex + 2, newProjectLine);
 9     //添加编译配置
10     var projectConfigStartIndex = solutionFileLines.FindIndex(i => i.Contains("ProjectConfigurationPlatforms"));
11     var projectConfigEndIndex = solutionFileLines.FindIndex(projectConfigStartIndex + 1, i => i.Contains("EndGlobalSection"));
12     solutionFileLines.Insert(projectConfigEndIndex, $"{{{_newProjectId}}}.Debug|Any CPU.Build.0 = Release|Any CPU");
13     solutionFileLines.Insert(projectConfigEndIndex, $"{{{_newProjectId}}}.Debug|Any CPU.Build.0 = Release|Any CPU");
14     solutionFileLines.Insert(projectConfigEndIndex, $"{{{_newProjectId}}}.Release|Any CPU.Build.0 = Release|Any CPU");
15     solutionFileLines.Insert(projectConfigEndIndex, $"{{{_newProjectId}}}.Release|Any CPU.Build.0 = Release|Any CPU");
16     File.WriteAllLines(_solutionFile, solutionFileLines, Encoding.UTF8);

2. Csprj文件,替换Nuget引用为源项目csproj的项目引用:

 1     public ReplacedFileRecord ReplaceNuget()
 2     {
 3         var nugetInfoReferences = CsProj.GetNugetReferences(Document).ToList();
 4         var referenceElement = nugetInfoReferences.FirstOrDefault(x => CsProj.GetNugetInfo(x).Name == _nugetName);
 5         if (referenceElement == null)
 6         {
 7             return null;
 8         }
 9         //获取Nuget引用信息
10         var replacedFileRecord = GetNugetReferenceInfo(referenceElement, nugetInfoReferences.IndexOf(referenceElement));
11         //删除Nuget的引用
12         referenceElement.Remove();
13         //添加源项目的引用
14         AddSourceReference();
15         SaveFile();
16         return replacedFileRecord;
17     }

一个csproj文件,可能会有多个替换Nuget的记录,这些记录用于后续的还原操作:

 1     /// <summary>
 2     /// 一个文件Nuget变更记录
 3     /// </summary>
 4     [DataContract]
 5     public class ReplacedFileRecord
 6     {
 7         /// <summary>
 8         /// Nuget名称
 9         /// </summary>
10         [DataMember]
11         public string NugetName { get; set; }
12         /// <summary>
13         /// 文件名称
14         /// </summary>
15         [DataMember]
16         public string FileName { get; set; }
17         /// <summary>
18         /// 变更位置
19         /// </summary>
20         [DataMember]
21         public int ModifiedLineIndex { get; set; }
22         /// <summary>
23         /// Nuget版本
24         /// </summary>
25         [DataMember]
26         public string Version { get; set; }
27         [CanBeNull]
28         [DataMember]
29         public string TargetFramework { get; set; }
30         [CanBeNull]
31         [DataMember]
32         public string NugetDllPath { get; set; }
33         /// <summary>
34         /// Nuget引用方式
35         /// </summary>
36         [DataMember]
37         public string ReferenceType { get; set; }
38     }

Nuget工具:Nuget工具_1.0.3.1012.exe,最新版以及源代码详见:WindowsOrg/NugetEfficientTool: VisualStudio项目开发-Nuget操作效率工具 (github.com),欢迎大家提交优化一起贡献代码

 

关键字:Nuget包管理、Nuget源代码调试、NugetEfficientTool

标签:csproj,管理工具,Nuget,版本,解决方案,var,NET,源代码
From: https://www.cnblogs.com/kybs0/p/18363275

相关文章

  • 通过Rancher管理Kubernetes 集群
    目录1.Rancher2.Rancher安装及配置2.1安装rancher2.2 rancher的浏览器使用1.RancherRancher是一个开源的企业级多集群Kubernetes管理平台,实现了Kubernetes集群在混合云+本地数据中心的集中部署与管理,以确保集群的安全性,加速企业数字化转型。超过40000家企......
  • 【Tarjan缩点】USACO5.3 校园网Network of Schools】
    [P2746USACO5.3]校园网NetworkofSchools大意:一个图可能有环a:求deg入度为0的点的个数b:至少加多少条边让图所有点可以互相到达思路:看代码#include<cstdio>#include<queue>#include<deque>#include<stack>#include<map>#include<cmath>#include<algorit......
  • 使用DBeaver(通用数据库管理工具)连接人大金仓数据库
    1、背景描述在信创的大背景下,信息技术人员开始需要频繁接触国产数据库。人大金仓数据库是国内先进的数据库产品,广泛服务于各个重点行业和关键领域,累计装机部署超百万套。2020年,人大金仓实现在国产数据库关键应用领域销售套数占比第一的市场地位。虽然人大金仓提供了官方的数据......
  • 记net 7.0 使用Windows 批处理 和exe 程序的快速打包 更新
     如图,项目路径,我们使用publis.bat批处理进行项目打包,将编译的项目文件压缩成zip包放到publish文件夹@echooffsetcur_path=%~dp0 setfe_build_path=%cur_path%build\setbe_pub_path=%cur_path%publish\setcompress_tool=%cur_path%tools\7za.exeecho*当前地......
  • .NET8 Blazor 从入门到精通:(二)组件
    目录Blazor组件基础路由导航参数组件参数路由参数生命周期事件状态更改组件事件Blazor组件基础新建一个项目命名为MyComponents,项目模板的交互类型选Auto,其它保持默认选项:客户端组件(Auto/WebAssembly):最终解决方案里面会有两个项目:服务器端项目、客户端项目,组件按......
  • .NET 8 跨平台高性能边缘采集网关
    目录前言项目介绍通道插件设备变量项目特点可视化操作脚本支持自定义插件支持性能断线缓存完整可商用的边缘网关项目插件采集插件业务插件项目展示1、ThingsGateway演示地址2、登录页面3、系统首页4、网关管理5、网关状态6、网关日志项目地址最后......
  • IoTSharp:基于 .NET 6.0 的开源物联网平台
    目录前言项目介绍为什么会有IoTSharp?IoTSharp能做什么?IoTSharp的亮点项目技术1、编程语言2、系统框架3、数据库支持4、消息队列与EventBus5、EventBus存储项目使用1、下载2、启动3、注册服务4、初始化influxdb5、注册6、运行项目地址总结最后前......
  • .NET CORE在publish的时候去掉pdb
     默认设置下,publish出来的文件其实是包含很多的pdb文件,即使你过程当中选择的是“输出为单一文件”: 想要设置为publish的时候不输出,有三种方法(推荐第三种):1.直接改项目的配置文件的配置:2.直接改Web项目的publish的文件的配置:在最终的Startup的项目(比如是Web)的publish配......
  • 界面控件DevExpress .NET MAUI v24.1 - 发布TreeView等新组件
    DevExpress拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpressDashboardeXpressApp框架、适用于VisualStudio的CodeRush等一系列辅助工具。屡获大奖的软件开发平台DevExpress今年第一个重要版本v23.1正式发布,该版本拥有众多新产品和数十个具有高影响力......
  • .NET 轻量化定时任务调度 FreeScheduler
    前言在平时项目开发中,定时任务调度是一项重要的功能,广泛应用于后台作业、计划任务和自动化脚本等模块。FreeScheduler是一款轻量级且功能强大的定时任务调度库,它支持临时的延时任务和重复循环任务(可持久化),能够按秒、每天/每周/每月固定时间或自定义间隔执行(CRON表达式)。此外......