0 Comments Posted in:

My usual approach for creating NuGet packages is to have a Git repository per NuGet package. This is a relatively simple and straightforward way of working, but when you're creating with multiple NuGet packages that all depend on each other, it's not always ideal.

For example, with NAudio, I've often thought about splitting it up into several smaller packages, e.g. NAudio.Core, NAudio.Asio, NAudio.MediaFoundation etc. However, I'd want to keep all the source in the same Git repository, and use local project references between them while developing to make debugging easier. At publish time, though, they'd need to reference each other as NuGet packages.

I'd assumed for ages that this required some complex build script syntax to achieve. I'd even done loads of web searches to try to find out how other people were achieving this setup, but came up blank every time.

However, it turns out that this capability is built right in with the SDK style csproj files, and really easy to achieve! Just create a couple of class libraries, add project references between them, and when you run dotnet pack, it just does the right thing and creates NuGet packages that depend on each other properly.

How to set this up

To explain what I mean and how to achieve this setup, here's some very simple instructions. We're going to create two NuGet packages - LibraryA and LibraryB, with LibraryA depending on LibraryB. We can actually set up the entire project structure including creating a .sln file and setting up the project references, using various dotnet CLI commands.

Let's start by creating the two projects (class libraries), a .sln file that includes both projects, and then ask for LibraryA to take a dependency on LibraryB:

md MultiPackageLibrary
cd MultiPackageLibrary
dotnet new classlib -o LibraryA
dotnet new classlib -o LibraryB
dotnet new solution
dotnet sln add LibraryA
dotnet sln add LibraryB
dotnet add LibraryA reference LibraryB

If we then look at LibraryA.csproj, we see it's generated a project reference from LibraryA to LibraryB:

  <ItemGroup>
    <ProjectReference Include="..\LibraryB\LibraryB.csproj" />
  </ItemGroup>

Let's create an interface in LibraryB...

namespace LibraryB
{
    public class IMyInterface
    {
    }
}

...and a concrete implementation of it in LibraryA:

using LibraryB;
namespace LibraryA
{
    public class MyClass : IMyInterface
    {
    }
}

Now we're ready to actually create our NuGet packages, which we can do with dotnet pack (and I want a release build):

dotnet pack -c Release

This will create LibraryA.1.0.0.nupkg and LibraryB.1.0.0.nupkg. And just to be sure that the dependencies are set up correctly, we can use the excellent free NuGet Package Explorer utility to look inside the LibraryA NuGet package and ensure that it correctly depends on LibraryB:

NuGet Package Explorer

Of course, one challenge with this approach is that if you have an automated CI server that publishes the packages to a NuGet feed, how does it know which NuGet package has changed? Probably the simplest option is to always up-version all the NuGet packages in the repo and republish them. But that might mean you sometimes unnecessarily publish new versions of a package without any underlying changes.

Anyway, hope someone else finds this useful - I wish I'd known about this a long time ago. Big thanks to John Wostenberg for alerting me to this capability.

Vote on HN