发布 NuGet 包所需了解的一切
Source: Dev.to
在上一篇文章中,我们从使用者的角度分析了如何在依赖地狱中生存。然而,技术职业生涯的真正飞跃发生在你不再只是下载包,而是开始设计包的时候。
NuGet 解决的根本问题并不是简单的*“下载 DLL”*,而是对架构层面 DRY(Don’t Repeat Yourself)原则的违背。
想象一下,你有一个 AuditLog.cs 或 StringUtils.cs 类。启动一个新微服务时,最快的做法是复制粘贴该文件。几个月后,你发现这段代码存在严重的安全漏洞,需要手动在 10 个不同的仓库中打补丁。
专业的解决方案是将其打包,而我们将一起了解如何使用 NuGet 完成这件事。
NuGet Library
创建一个库不需要魔法,只需要元数据。.csproj 文件不再是单纯的配置文件,而是产品清单。如果 .dll 是产品本身,那么 .csproj 就是包装标签;没有它,没人会知道这是什么、怎么用以及是否安全。
基本配置
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<PackageId>MyCompany.Common</PackageId>
<Version>1.0.0</Version>
<Authors>Equipo de Arquitectura</Authors>
<Company>Mi Empresa S.A.</Company>
<Description>Librería base para validaciones y logs estandarizados.</Description>
<PackageIcon>icon.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Deterministic>true</Deterministic>
<PackageTags>logs;validation;common;architecture</PackageTags>
<PackageOutputPath>./nupkg</PackageOutputPath>
<RepositoryUrl>https://github.com/mi-empresa/my-common-lib</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<IncludeSymbols>true</IncludeSymbols>
<IncludeSource>true</IncludeSource>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
</Project>
为什么每一行都很重要?
🎯 Target 的困境(多目标)
netstandard2.0:几乎可以在任何环境运行(包括 .NET Framework 4.6.1+)。net8.0:利用现代性能优化。
NuGet 会根据消费者项目自动提供正确的 DLL。
📁 资产(图标 & 自述文件)
PackageIcon:包含你的 logo(PNG 128×128)。PackageReadmeFile:README.md会在 Visual Studio 的 NuGet 选项卡中显示,提供即时文档。
🔒 确定性构建
Deterministic=true 确保只要代码未变,生成的二进制文件在位级上完全相同。这对安全校验和企业缓存至关重要。
📦 传递依赖
当你将 Serilog 声明为 PackageReference 时,任何使用你包的消费者都会自动获得它,避免手动安装。
🏷️ 仓库标签
RepositoryUrl 和 RepositoryType 将包与源码关联,提升信任度并方便审计。
🗂️ 版本策略
虽然这里使用了固定版本 (1.0.0),但在专业环境中建议使用 MinVer 等工具自动生成基于 Git Tag 的语义化版本。
⚖️ 法律授权
- 开源:使用标准标识符(MIT、Apache‑2.0 等)。
- 专有/企业:使用指向包内
LICENSE.txt文件的标识。

NuGet Tools
库会被集成到你的应用中,而 NuGet Tools 是随应用一起运行的程序(例如 dotnet‑ef)。你可以通过打包一个控制台应用来创建自己的企业工具。
PackAsTool
技术上的区别在于 PackAsTool 属性,它告诉 NuGet 该包包含可执行文件,而不是库。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<PackAsTool>true</PackAsTool>
<ToolCommandName>my-scaffolder</ToolCommandName>
<PackageId>MyCompany.Scaffolder</PackageId>
<Version>1.0.0</Version>
<PackageOutputPath>./nupkg</PackageOutputPath>
</PropertyGroup>
</Project>
工具使用
# 全局安装
dotnet tool install -g MyCompany.Scaffolder
# 运行
my-scaffolder "NuevoServicio"
💡 为了避免全局安装,你可以使用 本地工具(dotnet new tool-manifest),并通过 dotnet tool restore 共享版本。
分发策略
拥有 .nupkg 只是第一步。关键决策在于把它放在哪里。发布时,需要在 NuGet.config 中注册目标位置。该文件充当一个双向地址簿:既用于消费外部 feed 的包,也用于向其他团队或社区公开我们的包。
(继续介绍 NuGet.config 的配置、发布到 nuget.org、Azure Artifacts、GitHub Packages 等内容)