如何获取项目/解决方案任意深度的NuGet依赖树?
官方C# API实现方案
前置依赖
首先安装微软官方发布的NuGet相关NuGet包,这是NuGet.Core的官方替代实现,完全支持最新的项目格式和依赖规则:
NuGet.ProjectModel:负责解析项目资产文件、构建依赖模型NuGet.Common:提供通用枚举、工具类支持NuGet.Protocol(可选):如果需要从远程NuGet源直接拉取不在本地的包依赖树,可安装该包
核心实现逻辑
.NET 项目执行 dotnet restore 操作后,会在项目的obj目录下生成project.assets.json文件,该文件已经完整记录了当前项目全深度的所有依赖层级关系,不需要自行递归爬取NuGet源,解析效率极高。
代码示例
using NuGet.Common; using NuGet.ProjectModel; using System.Collections.Generic; using System.IO; using System.Linq; public class NuGetDependencyTreeReader { // 递归遍历依赖节点的辅助类 public class DependencyNode { public string PackageName { get; set; } public string PackageVersion { get; set; } public List<DependencyNode> Dependencies { get; set; } = new(); } public DependencyNode GetProjectDependencyTree(string projectAssetsFilePath) { // 读取assets文件 var lockFile = LockFileUtilities.GetLockFile(projectAssetsFilePath, NullLogger.Instance); if (lockFile == null) return null; // 获取项目根节点信息 var rootProject = lockFile.ProjectFileDependencyGroups.FirstOrDefault(); var rootNode = new DependencyNode { PackageName = lockFile.PackageSpec.Name, PackageVersion = lockFile.PackageSpec.Version.ToString() }; // 构建已加载包的缓存,避免循环依赖导致无限递归 var loadedPackages = new Dictionary<string, DependencyNode>(); var allLibraries = lockFile.Libraries.ToDictionary(lib => lib.Name, lib => lib); // 递归填充依赖 foreach (var rootDependency in rootProject.Dependencies) { rootNode.Dependencies.Add(BuildDependencyNode(rootDependency.Name, rootDependency.VersionRange.OriginalString, allLibraries, loadedPackages)); } return rootNode; } private DependencyNode BuildDependencyNode(string packageName, string version, IReadOnlyDictionary<string, LockFileLibrary> allLibraries, Dictionary<string, DependencyNode> loadedPackages) { var packageKey = $"{packageName}@{version}"; if (loadedPackages.TryGetValue(packageKey, out var existingNode)) { return existingNode; } if (!allLibraries.TryGetValue(packageName, out var library)) { return new DependencyNode { PackageName = packageName, PackageVersion = version }; } var node = new DependencyNode { PackageName = packageName, PackageVersion = library.Version.ToString() }; loadedPackages.Add(packageKey, node); foreach (var dependency in library.Dependencies) { node.Dependencies.Add(BuildDependencyNode(dependency.Id, dependency.VersionRange.OriginalString, allLibraries, loadedPackages)); } return node; } }
解决方案级别适配
如果需要获取整个解决方案的依赖树,只需要遍历解决方案下所有项目的obj目录,读取每个项目的project.assets.json文件,将所有项目的根依赖节点合并即可。如果项目未生成资产文件,可先通过C#调用dotnet restore <解决方案路径>命令生成,不需要额外依赖。
内容的提问来源于stack exchange,提问作者Andrey Skvortsov
相关产品推荐
相关产品推荐

