Search code examples
c#dllnugetdependency-management

How to stop transitive dependency from appearing in your project


For example I use a library B from NuGet in my project A :

Referencing:

<PackageReference Include="B" Version="1.0.0"/>

Usage:

namespace A.Helpers
{
    public interface Helper
    {
         A.Models.Output DoStuff(B.Input input);
    }
}

And also publish it to NuGet. After some time I notice that B uses a lot of different unnecessary dependencies like C, D, ..., ZZZ so my NuGet A also transitively references them.

If I reference it adding PrivateAssets tag instead:

<PackageReference Include="B" Version="1.0.0" PrivateAssets="All"/>

Then users of A lose access to class B.Input

How do I ship library A without passing unnecessary dependencies C, D, ..., ZZZ to the end user but still allow using class B.Input ?

Edit: I would like to clarify that unnecessary here means "not needed for functionality I am using or shipping". i.e. I use matrices and vectors from B, but B also provides means to work with graphics and references like System.Drawing and I prefer to not pass it further


Solution

  • (Converting my flippant comment to an answer because the OP said it was actually good advice (lol, but fair enough))

    Instructions: Break NuGet Package Seal in Event of Misbehaving Package Authors

    1. Find the offending .nupkg package file (either by copying it from its source, or from your ~/.nuget/packages/ directory.
      • Also check to see if there's a .snupkg or .symbols.nupkg file too.
    2. As a .nupkg is just a rebadged zip file, extract its contents to a new directory somewhere; you can use your favourite PKZIP tool (e.g. 7-Zip, PowerShell, WinZip, or even explorer.exe's painfully slow extraction wizard).
    3. In the root of the extracted contents, locate the {packageName}.nuspec file. Open it in Notepad or your editor of choice.
    4. Edit the <metadata>, <dependencies> and <dependency> elements to your liking. Some tips:
      • Don't confuse MSBuild <PackageReference /> and <ProjectReference /> with NuSpec <dependency> elements - they're similar but also different.

        • e.g. <dependency> has include="", exclude="" and , while <PackageReference /> has IncludeAssets="", ExcludeAssets="", and PrivateAssets="".
      • Consider adding the developmentDependency="true" attribute

      • Don't forget to change the NuSpec's <id> to be globally distinct from the original package you're modifying (the package name does not need to match any assembly names, it's entirely arbitrary).

        • And it's also good-form to append to the <description> element to document the changes you made so that other people (and future-you) won't be confused by the existence of DodgyPackage.1.0.0.nupkg next to DodgyPackageNowLessDodgy.0.1.0-dev.nupkg in the same package store.
    5. Then create a new empty .zip file, add the files back into it, and rename it to {yourNewPackageId}.{version}.nupkg and add it to your package store.