package-management
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNuGet Package Management
NuGet包管理
When to Use This Skill
什么时候使用本指南
Use this skill when:
- Adding, removing, or updating NuGet packages
- Setting up Central Package Management (CPM) for a solution
- Managing package versions across multiple projects
- Troubleshooting package conflicts or restore issues
当你遇到以下场景时可参考本指南:
- 添加、移除或更新NuGet包
- 为解决方案设置中央包管理(CPM)
- 跨多个项目管理包版本
- 排查包冲突或还原问题
Golden Rule: Never Edit XML Directly
黄金准则:永远不要直接编辑XML
Always use CLI commands to manage packages. Never manually edit or files.
dotnet.csprojDirectory.Packages.propsbash
undefined始终使用 CLI命令管理包。 永远不要手动编辑或文件。
dotnet.csprojDirectory.Packages.propsbash
undefinedDO: Use CLI commands
DO: Use CLI commands
dotnet add package Newtonsoft.Json
dotnet remove package Newtonsoft.Json
dotnet list package --outdated
dotnet add package Newtonsoft.Json
dotnet remove package Newtonsoft.Json
dotnet list package --outdated
DON'T: Edit XML directly
DON'T: Edit XML directly
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
**Why:**
- CLI validates package exists and resolves correct version
- Handles transitive dependencies correctly
- Updates lock files if present
- Avoids typos and malformed XML
- Works correctly with CPM
---
**为什么要遵守这个准则:**
- CLI会验证包是否存在并解析正确的版本
- 正确处理传递依赖项
- 如有锁文件会同步更新
- 避免输入错误和XML格式错误
- 与CPM完美兼容
---Central Package Management (CPM)
中央包管理(CPM)
CPM centralizes all package versions in one file, eliminating version conflicts across projects.
CPM将所有包版本集中存放在单个文件中,消除跨项目的版本冲突。
Enable CPM
启用CPM
Create in solution root:
Directory.Packages.propsxml
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Serilog" Version="4.0.0" />
<PackageVersion Include="xunit" Version="2.9.2" />
</ItemGroup>
</Project>在解决方案根目录下创建文件:
Directory.Packages.propsxml
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Serilog" Version="4.0.0" />
<PackageVersion Include="xunit" Version="2.9.2" />
</ItemGroup>
</Project>Project Files with CPM
启用CPM后的项目文件
Projects reference packages without versions:
xml
<!-- src/MyApp/MyApp.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Serilog" />
</ItemGroup>
</Project>项目引用包时无需指定版本:
xml
<!-- src/MyApp/MyApp.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Serilog" />
</ItemGroup>
</Project>Adding Packages with CPM
启用CPM时添加包
bash
undefinedbash
undefinedAdds to Directory.Packages.props AND project file
Adds to Directory.Packages.props AND project file
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.Console
Result in Directory.Packages.props:
Result in Directory.Packages.props:
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
Result in project file:
Result in project file:
<PackageReference Include="Serilog.Sinks.Console" />
<PackageReference Include="Serilog.Sinks.Console" />
---
---Shared Version Variables
共享版本变量
Group related packages with shared version variables:
xml
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<!-- Shared version variables -->
<PropertyGroup Label="SharedVersions">
<AkkaVersion>1.5.59</AkkaVersion>
<AkkaHostingVersion>1.5.59</AkkaHostingVersion>
<AspireVersion>9.0.0</AspireVersion>
<OpenTelemetryVersion>1.11.0</OpenTelemetryVersion>
<XunitVersion>2.9.2</XunitVersion>
</PropertyGroup>
<!-- Akka.NET packages - all use same version -->
<ItemGroup Label="Akka.NET">
<PackageVersion Include="Akka" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster.Sharding" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster.Tools" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Persistence" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Streams" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Hosting" Version="$(AkkaHostingVersion)" />
<PackageVersion Include="Akka.Cluster.Hosting" Version="$(AkkaHostingVersion)" />
</ItemGroup>
<!-- Aspire packages -->
<ItemGroup Label="Aspire">
<PackageVersion Include="Aspire.Hosting" Version="$(AspireVersion)" />
<PackageVersion Include="Aspire.Hosting.AppHost" Version="$(AspireVersion)" />
<PackageVersion Include="Aspire.Hosting.PostgreSQL" Version="$(AspireVersion)" />
<PackageVersion Include="Aspire.Hosting.Testing" Version="$(AspireVersion)" />
</ItemGroup>
<!-- OpenTelemetry packages -->
<ItemGroup Label="OpenTelemetry">
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="$(OpenTelemetryVersion)" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="$(OpenTelemetryVersion)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="$(OpenTelemetryVersion)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="$(OpenTelemetryVersion)" />
</ItemGroup>
<!-- Testing -->
<ItemGroup Label="Testing">
<PackageVersion Include="xunit" Version="$(XunitVersion)" />
<PackageVersion Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
<PackageVersion Include="Verify.Xunit" Version="26.0.0" />
</ItemGroup>
</Project>Benefits:
- Update all Akka packages by changing one variable
- Clear organization with labeled ItemGroups
- Prevents version mismatches in related packages
使用共享版本变量对相关包进行分组:
xml
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<!-- Shared version variables -->
<PropertyGroup Label="SharedVersions">
<AkkaVersion>1.5.59</AkkaVersion>
<AkkaHostingVersion>1.5.59</AkkaHostingVersion>
<AspireVersion>9.0.0</AspireVersion>
<OpenTelemetryVersion>1.11.0</OpenTelemetryVersion>
<XunitVersion>2.9.2</XunitVersion>
</PropertyGroup>
<!-- Akka.NET packages - all use same version -->
<ItemGroup Label="Akka.NET">
<PackageVersion Include="Akka" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster.Sharding" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster.Tools" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Persistence" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Streams" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Hosting" Version="$(AkkaHostingVersion)" />
<PackageVersion Include="Akka.Cluster.Hosting" Version="$(AkkaHostingVersion)" />
</ItemGroup>
<!-- Aspire packages -->
<ItemGroup Label="Aspire">
<PackageVersion Include="Aspire.Hosting" Version="$(AspireVersion)" />
<PackageVersion Include="Aspire.Hosting.AppHost" Version="$(AspireVersion)" />
<PackageVersion Include="Aspire.Hosting.PostgreSQL" Version="$(AspireVersion)" />
<PackageVersion Include="Aspire.Hosting.Testing" Version="$(AspireVersion)" />
</ItemGroup>
<!-- OpenTelemetry packages -->
<ItemGroup Label="OpenTelemetry">
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="$(OpenTelemetryVersion)" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="$(OpenTelemetryVersion)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="$(OpenTelemetryVersion)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="$(OpenTelemetryVersion)" />
</ItemGroup>
<!-- Testing -->
<ItemGroup Label="Testing">
<PackageVersion Include="xunit" Version="$(XunitVersion)" />
<PackageVersion Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
<PackageVersion Include="Verify.Xunit" Version="26.0.0" />
</ItemGroup>
</Project>优势:
- 只需修改一个变量即可更新所有Akka相关包
- 带标签的ItemGroup结构清晰易维护
- 避免相关包出现版本不匹配问题
When NOT to Use CPM
什么时候不适合使用CPM
Central Package Management isn't always the right choice:
中央包管理并非适用于所有场景:
Legacy Projects
遗留项目
Migrating an existing large solution to CPM can introduce issues:
- Existing version conflicts become visible all at once
- Some packages may have intentional version differences
- Migration requires touching many files simultaneously
Recommendation: For legacy projects, migrate incrementally or stick with per-project versioning if it's working.
将现有大型解决方案迁移到CPM可能会引发问题:
- 现有版本冲突会一次性全部暴露
- 部分包可能有意使用不同版本
- 迁移需要同时修改大量文件
建议:对于遗留项目,如果现有按项目管理版本的方式运行良好,建议逐步迁移或继续沿用原有方式。
Version Ranges
版本范围
CPM requires exact versions - it doesn't support version ranges:
xml
<!-- NOT supported with CPM -->
<PackageVersion Include="Newtonsoft.Json" Version="[13.0,14.0)" />
<!-- Must use exact version -->
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />If you need version ranges (rare, but some library scenarios require it), CPM won't work.
CPM要求使用精确版本,不支持版本范围:
xml
<!-- NOT supported with CPM -->
<PackageVersion Include="Newtonsoft.Json" Version="[13.0,14.0)" />
<!-- Must use exact version -->
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />如果需要使用版本范围(场景少见,仅部分类库开发场景需要),则无法使用CPM。
Older .NET Versions
旧版.NET版本
CPM requires:
- .NET SDK 6.0.300+ or later
- NuGet 6.2+ or later
- Visual Studio 2022 17.2+ or later
If you're targeting older SDK versions or have team members on older tooling, CPM may cause build failures.
CPM要求:
- .NET SDK 6.0.300+ 或更高版本
- NuGet 6.2+ 或更高版本
- Visual Studio 2022 17.2+ 或更高版本
如果你使用的是旧版SDK,或者团队成员使用旧版工具,CPM可能会导致构建失败。
Multi-Repo Solutions
多仓库解决方案
If your solution spans multiple repositories that are built independently, CPM's single won't help - each repo needs its own.
Directory.Packages.props如果你的解决方案跨多个独立构建的仓库,CPM的单个文件无法覆盖所有仓库,每个仓库需要单独配置。
Directory.Packages.propsCLI Command Reference
CLI命令参考
Adding Packages
添加包
bash
undefinedbash
undefinedAdd latest stable version
Add latest stable version
dotnet add package Serilog
dotnet add package Serilog
Add specific version
Add specific version
dotnet add package Serilog --version 4.0.0
dotnet add package Serilog --version 4.0.0
Add prerelease
Add prerelease
dotnet add package Serilog --prerelease
dotnet add package Serilog --prerelease
Add to specific project
Add to specific project
dotnet add src/MyApp/MyApp.csproj package Serilog
undefineddotnet add src/MyApp/MyApp.csproj package Serilog
undefinedRemoving Packages
移除包
bash
undefinedbash
undefinedRemove from current project
Remove from current project
dotnet remove package Serilog
dotnet remove package Serilog
Remove from specific project
Remove from specific project
dotnet remove src/MyApp/MyApp.csproj package Serilog
undefineddotnet remove src/MyApp/MyApp.csproj package Serilog
undefinedListing Packages
列出包
bash
undefinedbash
undefinedList all packages in solution
List all packages in solution
dotnet list package
dotnet list package
Show outdated packages
Show outdated packages
dotnet list package --outdated
dotnet list package --outdated
Include transitive dependencies
Include transitive dependencies
dotnet list package --include-transitive
dotnet list package --include-transitive
Show vulnerable packages
Show vulnerable packages
dotnet list package --vulnerable
dotnet list package --vulnerable
Show deprecated packages
Show deprecated packages
dotnet list package --deprecated
undefineddotnet list package --deprecated
undefinedUpdating Packages
更新包
bash
undefinedbash
undefinedWith CPM: Edit the version in Directory.Packages.props
With CPM: Edit the version in Directory.Packages.props
Then restore to apply
Then restore to apply
dotnet restore
dotnet restore
Without CPM: Remove and add with new version
Without CPM: Remove and add with new version
dotnet remove package Serilog
dotnet add package Serilog --version 4.1.0
dotnet remove package Serilog
dotnet add package Serilog --version 4.1.0
Or use dotnet-outdated tool (recommended)
Or use dotnet-outdated tool (recommended)
dotnet tool install --global dotnet-outdated-tool
dotnet outdated --upgrade
undefineddotnet tool install --global dotnet-outdated-tool
dotnet outdated --upgrade
undefinedRestore and Clean
还原与清理
bash
undefinedbash
undefinedRestore packages
Restore packages
dotnet restore
dotnet restore
Clear local cache (troubleshooting)
Clear local cache (troubleshooting)
dotnet nuget locals all --clear
dotnet nuget locals all --clear
Force restore (ignore cache)
Force restore (ignore cache)
dotnet restore --force
---dotnet restore --force
---Package Sources
包源
List Sources
列出源
bash
dotnet nuget list sourcebash
dotnet nuget list sourceAdd Private Feed
添加私有源
bash
undefinedbash
undefinedAdd authenticated feed
Add authenticated feed
dotnet nuget add source https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json
--name MyFeed
--username az
--password $PAT
--store-password-in-clear-text
--name MyFeed
--username az
--password $PAT
--store-password-in-clear-text
undefineddotnet nuget add source https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json
--name MyFeed
--username az
--password $PAT
--store-password-in-clear-text
--name MyFeed
--username az
--password $PAT
--store-password-in-clear-text
undefinedNuGet.config
NuGet.config
For solution-specific sources, create :
NuGet.configxml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="MyPrivateFeed" value="https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json" />
</packageSources>
<packageSourceCredentials>
<MyPrivateFeed>
<add key="Username" value="az" />
<add key="ClearTextPassword" value="%NUGET_PAT%" />
</MyPrivateFeed>
</packageSourceCredentials>
</configuration>如需配置解决方案专属源,可创建文件:
NuGet.configxml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="MyPrivateFeed" value="https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json" />
</packageSources>
<packageSourceCredentials>
<MyPrivateFeed>
<add key="Username" value="az" />
<add key="ClearTextPassword" value="%NUGET_PAT%" />
</MyPrivateFeed>
</packageSourceCredentials>
</configuration>Common Patterns
常见使用模式
Development-Only Packages
仅开发环境使用的包
xml
<!-- Directory.Packages.props -->
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<!-- Project file - mark as development dependency -->
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />xml
<!-- Directory.Packages.props -->
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<!-- Project file - mark as development dependency -->
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />Conditional Packages
条件包
xml
<!-- Only include in Debug builds -->
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
<PackageReference Include="JetBrains.Annotations" />
</ItemGroup>
<!-- Platform-specific -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="System.Text.Json" />
</ItemGroup>xml
<!-- Only include in Debug builds -->
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
<PackageReference Include="JetBrains.Annotations" />
</ItemGroup>
<!-- Platform-specific -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="System.Text.Json" />
</ItemGroup>Version Override (Escape Hatch)
版本覆盖(应急方案)
When you must override CPM for one project (rare):
xml
<!-- Project file - use sparingly! -->
<PackageReference Include="Newtonsoft.Json" VersionOverride="12.0.3" />Warning: This is detected by Slopwatch (see skill) as potential slop.
dotnet/slopwatch当你必须为某个项目覆盖CPM的版本配置时(非常少见):
xml
<!-- Project file - use sparingly! -->
<PackageReference Include="Newtonsoft.Json" VersionOverride="12.0.3" />警告:这种操作会被Slopwatch(参见指南)识别为潜在不规范操作。
dotnet/slopwatchTroubleshooting
问题排查
Version Conflicts
版本冲突
bash
undefinedbash
undefinedSee full dependency tree
See full dependency tree
dotnet list package --include-transitive
dotnet list package --include-transitive
Find what's pulling in a specific package
Find what's pulling in a specific package
dotnet list package --include-transitive | grep -i "PackageName"
undefineddotnet list package --include-transitive | grep -i "PackageName"
undefinedRestore Failures
还原失败
bash
undefinedbash
undefinedClear all caches
Clear all caches
dotnet nuget locals all --clear
dotnet nuget locals all --clear
Restore with detailed logging
Restore with detailed logging
dotnet restore --verbosity detailed
dotnet restore --verbosity detailed
Check for locked packages
Check for locked packages
cat packages.lock.json
undefinedcat packages.lock.json
undefinedLock Files
锁文件
For reproducible builds, use package lock files:
xml
<!-- Directory.Build.props -->
<PropertyGroup>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>Then commit files.
packages.lock.json如需可复现的构建,可使用包锁文件:
xml
<!-- Directory.Build.props -->
<PropertyGroup>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>然后提交文件到代码仓库。
packages.lock.jsonAnti-Patterns
反模式
Don't: Edit XML Directly
禁止:直接编辑XML
xml
<!-- BAD: Manual XML editing -->
<PackageReference Include="Typo.Package" Version="1.0.0" />
<!-- Package might not exist! CLI would catch this. -->xml
<!-- BAD: Manual XML editing -->
<PackageReference Include="Typo.Package" Version="1.0.0" />
<!-- Package might not exist! CLI would catch this. -->Don't: Inline Versions with CPM
禁止:启用CPM时内联版本
xml
<!-- BAD: Bypasses CPM -->
<PackageReference Include="Serilog" Version="4.0.0" />
<!-- GOOD: Version comes from Directory.Packages.props -->
<PackageReference Include="Serilog" />xml
<!-- BAD: Bypasses CPM -->
<PackageReference Include="Serilog" Version="4.0.0" />
<!-- GOOD: Version comes from Directory.Packages.props -->
<PackageReference Include="Serilog" />Don't: Mix Version Management
禁止:混合使用版本管理方式
xml
<!-- BAD: Some versions in CPM, some inline -->
<PackageReference Include="Serilog" /> <!-- From CPM -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <!-- Inline -->xml
<!-- BAD: Some versions in CPM, some inline -->
<PackageReference Include="Serilog" /> <!-- From CPM -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <!-- Inline -->Don't: Forget Shared Variables
禁止:忘记使用共享变量
xml
<!-- BAD: Related packages with different versions -->
<PackageVersion Include="Akka" Version="1.5.59" />
<PackageVersion Include="Akka.Cluster" Version="1.5.58" /> <!-- Mismatch! -->
<!-- GOOD: Use shared variable -->
<PackageVersion Include="Akka" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />xml
<!-- BAD: Related packages with different versions -->
<PackageVersion Include="Akka" Version="1.5.59" />
<PackageVersion Include="Akka.Cluster" Version="1.5.58" /> <!-- Mismatch! -->
<!-- GOOD: Use shared variable -->
<PackageVersion Include="Akka" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />Quick Reference
快速参考
| Task | Command |
|---|---|
| Add package | |
| Add specific version | |
| Remove package | |
| List packages | |
| Show outdated | |
| Show vulnerable | |
| Restore | |
| Clear cache | |
| 任务 | 命令 |
|---|---|
| 添加包 | |
| 添加指定版本 | |
| 移除包 | |
| 列出包 | |
| 查看过期包 | |
| 查看存在漏洞的包 | |
| 还原包 | |
| 清除缓存 | |
Resources
参考资源
- Central Package Management: https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management
- dotnet CLI Reference: https://learn.microsoft.com/en-us/dotnet/core/tools/
- NuGet.config Reference: https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file