掌握在 .NET 中使用 NuGet 包

发布: (2025年12月15日 GMT+8 19:07)
5 min read
原文: Dev.to

Source: Dev.to

什么是真正的 NuGet?

想象 NuGet 是 .NET 版的 Amazon 或 Mercado Libre。你不需要自己制造每个螺丝钉,而是从商店里买来。

  • Package(包): 你购买的产品(Newtonsoft.Json、EntityFramework)。
  • Source(Feed,源): 存放这些包的仓库或商店。

我的包会去哪里?

很多开发者以为执行 dotnet restore 时,DLL 会 神奇 地出现在项目里。了解真实的流程非常重要,才能知道背后到底发生了什么:

Request(请求): 你的项目(.csproj)请求 Newtonsoft.Json v13.0.1。
Restore(还原): NuGet 在已配置的 Sources 中查找。
Global Packages Folder(全局包文件夹): NuGet 将包下载并解压到用户的全局文件夹(Windows 通常是 %userprofile%\.nuget\packages,Linux/Mac 是 ~/.nuget/packages)。不会保存在你的项目内部。
Build(构建): 编译时,.NET 会从该全局文件夹读取 DLL,并复制到 bin/Debugbin/Release 目录。

Diagrama de flujo: Ciclo de vida de un paquete NuGet

这有什么意义? 因为它可以节省空间。如果有 10 个项目使用同一个库,磁盘上只会下载一次。

配置层级

在写任何配置之前,你必须了解 NuGet 的“思考方式”。执行 restore 时,它不仅查看你的项目,还会按照严格的层级级联合并配置:

  • 机器级(Machine Level): 这个文件往往根本不存在或是空的,除非管理员手动放置。
  • 用户级(User Level): 最常见的 (%appdata%\NuGet\NuGet.Config),随着时间会积累大量 “数字垃圾”
  • 目录级(递归,Directory Level): NuGet 会在解决方案所在文件夹查找…如果没有找到,就向上到父文件夹,再到祖父文件夹,直至磁盘根目录。

“在我的机器上能跑” 的根源 🤷‍♂️

Meme: It works on my machine

这就是著名的 meme 的来源。假设你在 用户级 配置了一个私有 feed,因为你在公司里有多个项目要用。你新建一个项目,编译完美。你的同事克隆仓库后尝试编译,却报错。

为什么? 因为你的项目依赖了只存在于你本地用户配置中的 不可见 配置。对同事来说,这个 feed 并不存在。

检测实际使用的配置

在解决方案根目录执行:

dotnet nuget list source

该命令会显示 NuGet 在该目录实际使用的、合并后的所有源列表。如果看到陌生的路径或已下线的服务器,那就是继承导致的问题。

NuGet.config

在解决方案根目录显式创建 NuGet.config 文件可以打断有害的继承链,确保项目对所有人都可用。

  
     elimina toda la "basura" heredada del usuario o máquina -->
    

    
    

    
    

    
    

    
    
  

  
  
    
  

  
    
    
      
      
    
  

这样配置的好处

  • 🛡 隔离: 使用 “ 可以保护项目不受全局破损配置的影响。
  • 🛠 独立性: 新开发者只需要 git clonedotnet restore
  • 🔄 CI/CD 友好: 流水线明确知道去哪里找依赖,不会出现奇怪的步骤。

优先级的混乱

如果你同时配置了 nuget.orgGitHubFeed,且两者都包含名为 Newtonsoft.Json 的包,究竟会下载哪个?

Meme Spiderman señalándose: Conflicto de nombres de paquetes

NuGet 采用 “先响应者” 的策略,这带来两个风险:

  1. 性能: 在找到私有包之前,会先在公共仓库里搜索。
  2. 安全: 攻击者可能在 nuget.org 上上传一个与内部包同名的恶意包(例如 MiBanco.Core),你的项目可能在不知情的情况下下载到攻击者的包。 🚨

Diagrama de amenaza: Dependency Confusion

Back to Blog

相关文章

阅读更多 »