March 15, 2024 09:18 by
Peter
Dependency management is a key feature of NuGet. It may be simple to manage dependencies for a single project. As multi-project solutions expand in size and complexity, maintaining dependencies can become difficult.
NuGet's central package management (CPM) features allow you to manage shared dependencies for multiple projects from a single, convenient location.
NuGet package dependencies
NuGet package dependencies have been managed in the following methods.
- packages.config: An XML file used by earlier project types to keep track of the packages that were referenced.
- <PackageReference />: NuGet package dependencies are described by an XML element used in MSBuild projects.
Enabling Central Package Management
You must create a Directory.Packages.props file at the root of your repository and set the MSBuild value ManagePackageVersionsCentrally to true in order to begin using central package management.
Then, using <PackageVersion /> elements that identify the package ID and version, you declare each of the corresponding package versions needed for your projects inside.
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="{{package name}}" Version="{{version number}}" />
</ItemGroup>
</Project>
For each of the projects, we need to define package references, and each of the projects belongs to the same version.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="{{package name}}" />
</ItemGroup>
</Project>
You're controlling your versions centrally and utilizing central package management now!
Let’s check with the demo.
Create one application for whatever you want for the project. Here I have created the console application for demo purposes. In the above image, CPMDemo is the console application, and CPMDemo.Utility is the class library project.
We can create Directory.Packages.props is the root-level file in our console application.
Here is the content of the directory package file.
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="6.0.27" />
</ItemGroup>
</Project>
Here is the content of the CPMDemo.csproj changes.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Microsoft.EntityFrameworkCore" />
</ItemGroup>
</Project>
Here is the content of the CPMDemo.Utility.csproj changes.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Microsoft.EntityFrameworkCore" />
</ItemGroup>
</Project>
Once you have completed the above changes on your application side, you just need to build the solution, and then after expanding the dependencies and expanding the packages as well, you will see the packages have been added to your application with the mentioned package versions.
Below is a screenshot taken before building the solution, so at that time we hadn’t added any packages to our application.
Below is a screenshot after building the solution and being able to see the added packages in our application.
Central Package Management rules
There are several restrictions governing the location of the Directory.Packages.props file within a repository's directory as well as its context. For the sake of simplicity, each project is evaluated using a single Directory.Packages.props file.
This indicates that the file nearest to the directory of your project will be considered for it if you have several Directory.Packages.props files in your repository. This gives you additional authority over your repository at different levels.
Repository structure
As an illustration, look at the repository structure below:
Here is the explanation for better understanding.
- ProjectName1 will assess the Directory.Packages.props file in the Repository Name\Solution1\ directory.
- ProjectName2 will assess the Directory.Packages.props file in the Repository Name\ directory.
In this manner, we can concentrate the packages that we need on the application side. It will also be simple to maintain—we just need to change one location, and it will reflect everywhere.
Happy learning!!