O que Gerenciamento de Pacotes NuGet faz?
Quando Usar Esta Habilidade
Use esta habilidade quando:
- Adicionar, remover ou atualizar pacotes NuGet
- Configurar o Gerenciamento Central de Pacotes (CPM) para uma solução
- Gerenciar versões de pacotes em vários projetos
- Solucionar conflitos de pacotes ou problemas de restauração
Regra de Ouro: Nunca Editar XML Diretamente
Sempre use comandos da CLI dotnet para gerenciar pacotes. Nunca edite manualmente arquivos .csproj ou Directory.Packages.props.
# CORRETO: Use comandos da CLI
dotnet add package Newtonsoft.Json
dotnet remove package Newtonsoft.Json
dotnet list package --outdated
# ERRADO: Editar XML diretamente
# <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
Por quê:
- A CLI valida se o pacote existe e resolve a versão correta
- Lida corretamente com dependências transitivas
- Atualiza arquivos de bloqueio, se presentes
- Evita erros de digitação e XML malformado
- Funciona corretamente com CPM
Gerenciamento Central de Pacotes (CPM)
O CPM centraliza todas as versões de pacotes em um único arquivo, eliminando conflitos de versão entre projetos.
Habilitar CPM
Crie Directory.Packages.props na raiz da solução:
<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>
Arquivos de Projeto com CPM
Os projetos referenciam pacotes sem versões:
<!-- src/MyApp/MyApp.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Serilog" />
</ItemGroup>
</Project>
Adicionando Pacotes com CPM
# Adiciona ao Directory.Packages.props E ao arquivo de projeto
dotnet add package Serilog.Sinks.Console
# Resultado em Directory.Packages.props:
# <PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
# Resultado no arquivo de projeto:
# <PackageReference Include="Serilog.Sinks.Console" />
Variáveis de Versão Compartilhadas
Agrupe pacotes relacionados com variáveis de versão compartilhadas:
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<!-- Variáveis de versão compartilhadas -->
<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>
<!-- Pacotes Akka.NET - todos usam a mesma versão -->
<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>
<!-- Pacotes Aspire -->
<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>
<!-- Pacotes OpenTelemetry -->
<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>
<!-- Testes -->
<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>
Benefícios:
- Atualize todos os pacotes Akka alterando uma única variável
- Organização clara com ItemGroups rotulados
- Previne incompatibilidades de versão em pacotes relacionados
Quando NÃO Usar CPM
O Gerenciamento Central de Pacotes nem sempre é a escolha certa:
Projetos Legados
Migrar uma solução grande existente para CPM pode introduzir problemas:
- Conflitos de versão existentes tornam-se visíveis de uma só vez
- Alguns pacotes podem ter diferenças intencionais de versão
- A migração exige alterar muitos arquivos simultaneamente
Recomendação: Para projetos legados, migre incrementalmente ou mantenha a versão por projeto se estiver funcionando.
Intervalos de Versão
O CPM exige versões exatas – não suporta intervalos de versão:
<!-- NÃO suportado com CPM -->
<PackageVersion Include="Newtonsoft.Json" Version="[13.0,14.0)" />
<!-- Deve usar versão exata -->
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
Se você precisar de intervalos de versão (raro, mas alguns cenários de bibliotecas exigem), o CPM não funcionará.
Versões Antigas do .NET
O CPM requer:
- .NET SDK 6.0.300+ ou superior
- NuGet 6.2+ ou superior
- Visual Studio 2022 17.2+ ou superior
Se você estiver visando versões mais antigas do SDK ou tiver membros da equipe com ferramentas antigas, o CPM pode causar falhas de compilação.
Soluções Multi-Repositório
Se sua solução abranger vários repositórios que são compilados independentemente, o único arquivo Directory.Packages.props do CPM não ajudará – cada repositório precisa do seu próprio.
Referência de Comandos CLI
Adicionando Pacotes
# Adicionar a versão estável mais recente
dotnet add package Serilog
# Adicionar versão específica
dotnet add package Serilog --version 4.0.0
# Adicionar pré-lançamento
dotnet add package Serilog --prerelease
# Adicionar a um projeto específico
dotnet add src/MyApp/MyApp.csproj package Serilog
Removendo Pacotes
# Remover do projeto atual
dotnet remove package Serilog
# Remover de um projeto específico
dotnet remove src/MyApp/MyApp.csproj package Serilog
Listando Pacotes
# Listar todos os pacotes na solução
dotnet list package
# Mostrar pacotes desatualizados
dotnet list package --outdated
# Incluir dependências transitivas
dotnet list package --include-transitive
# Mostrar pacotes vulneráveis
dotnet list package --vulnerable
# Mostrar pacotes obsoletos
dotnet list package --deprecated
Atualizando Pacotes
# Com CPM: Edite a versão em Directory.Packages.props
# Em seguida, restaure para aplicar
dotnet restore
# Sem CPM: Remova e adicione com nova versão
dotnet remove package Serilog
dotnet add package Serilog --version 4.1.0
# Ou use a ferramenta dotnet-outdated (recomendado)
dotnet tool install --global dotnet-outdated-tool
dotnet outdated --upgrade
Restauração e Limpeza
# Restaurar pacotes
dotnet restore
# Limpar cache local (solução de problemas)
dotnet nuget locals all --clear
# Forçar restauração (ignorar cache)
dotnet restore --force
Fontes de Pacotes
Listar Fontes
dotnet nuget list source
Adicionar Feed Privado
# Adicionar feed autenticado
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
NuGet.config
Para fontes específicas da solução, crie NuGet.config:
<?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>
Padrões Comuns
Pacotes Somente para Desenvolvimento
<!-- Directory.Packages.props -->
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<!-- Arquivo de projeto - marcar como dependência de desenvolvimento -->
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
Pacotes Condicionais
<!-- Incluir apenas em compilações Debug -->
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
<PackageReference Include="JetBrains.Annotations" />
</ItemGroup>
<!-- Específico de plataforma -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="System.Text.Json" />
</ItemGroup>
Substituição de Versão (Saída de Emergência)
Quando você precisar substituir o CPM para um projeto (raro):
<!-- Arquivo de projeto - usar com moderação! -->
<PackageReference Include="Newtonsoft.Json" VersionOverride="12.0.3" />
Aviso: Isso é detectado pelo Slopwatch (veja a habilidade dotnet/slopwatch) como potencial slop.
Solução de Problemas
Conflitos de Versão
# Ver a árvore completa de dependências
dotnet list package --include-transitive
# Descobrir o que está puxando um pacote específico
dotnet list package --include-transitive | grep -i "PackageName"
Falhas na Restauração
# Limpar todos os caches
dotnet nuget locals all --clear
# Restaurar com logs detalhados
dotnet restore --verbosity detailed
# Verificar pacotes bloqueados
cat packages.lock.json
Arquivos de Bloqueio
Para compilações reproduzíveis, use arquivos de bloqueio de pacotes:
<!-- Directory.Build.props -->
<PropertyGroup>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>
Em seguida, commite os arquivos packages.lock.json.
Anti-Padrões
Não Faça: Editar XML Diretamente
<!-- RUIM: Edição manual de XML -->
<PackageReference Include="Typo.Package" Version="1.0.0" />
<!-- O pacote pode não existir! A CLI detectaria isso. -->
Não Faça: Versões Inline com CPM
<!-- RUIM: Ignora o CPM -->
<PackageReference Include="Serilog" Version="4.0.0" />
<!-- BOM: A versão vem do Directory.Packages.props -->
<PackageReference Include="Serilog" />
Não Faça: Misturar Gerenciamento de Versão
<!-- RUIM: Algumas versões no CPM, outras inline -->
<PackageReference Include="Serilog" /> <!-- Do CPM -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <!-- Inline -->
Não Faça: Esquecer Variáveis Compartilhadas
<!-- RUIM: Pacotes relacionados com versões diferentes -->
<PackageVersion Include="Akka" Version="1.5.59" />
<PackageVersion Include="Akka.Cluster" Version="1.5.58" /> <!-- Inconsistente! -->
<!-- BOM: Use variável compartilhada -->
<PackageVersion Include="Akka" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />
Referência Rápida
| Tarefa | Comando |
|---|---|
| Adicionar pacote | dotnet add package <nome> |
| Adicionar versão específica | dotnet add package <nome> --version <ver> |
| Remover pacote | dotnet remove package <nome> |
| Listar pacotes | dotnet list package |
| Mostrar desatualizados | dotnet list package --outdated |
| Mostrar vulneráveis | dotnet list package --vulnerable |
| Restaurar | dotnet restore |
| Limpar cache | dotnet nuget locals all --clear |
Recursos
- 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