How to resolve NuGet dependency hell

Unity package isn’t a good example because you should use it only in one place called Composition Root. And Composition Root should be as close as it can be to application entry point. In your example it is CompanyName.SomeSolution.Application

Apart from that, where I work now, exactly the same problem appears. And what I see, the problem is often introduced by cross-cutting concerns like logging. The solution you can apply is to convert your third-party dependencies to first-party dependencies. You can do that by introducing abstractions for that concepts. Actually, doing this have other benefits like:

  • more maintainable code
  • better testability
  • get rid of unwanted dependency (every client of CompanyName.SDK really needs the Unity dependency?)

So, let’s take for an example imaginary .NET Logging library:

CompanyName.SDK.dll depends on .NET Logging 3.0
CompanyName.SomeSolution.Project1 depends on .NET Logging 2.0
CompanyName.SomeSolution.Project2 depends on .NET Logging 1.0

There are breaking changes between versions of .NET Logging.

You can create your own first-party dependency by introducing ILogger interface:

public interface ILogger
{
    void LogWarning();
    void LogError();
    void LogInfo();
} 

CompanyName.SomeSolution.Project1 and CompanyName.SomeSolution.Project2 should use ILogger interface. They are dependent on ILogger interface first-party dependency. Now you keep that .NET Logging library behind one place and it’s easy to perform update because you have to do it in one place. Also breaking changes between versions are no longer a problem, because one version of .NET Logging library is used.

The actual implementation of ILogger interface should be in different assembly and it should be only place where you reference .NET Logging library.
In CompanyName.SomeSolution.Application in place where you compose your application you should now map ILogger abstraction to concrete implementation.

We are using that approach and we are also using NuGet for distribute our abstractions and our implementations. Unfortunately, issues with versions can appear with your own packages. To avoid that issues apply Semantic Versioning in packages you deploy via NuGet for your company. If something change in in your code base that is distributed via NuGet you should change in all of the packages that are distributed via NuGet. For example we have in our local NuGet server :

  • DomainModel
  • Services.Implementation.SomeFancyMessagingLibrary (that references DomainModel and SomeFancyMessagingLibrary)
  • and more…

Version between this packages are synchronized, if version is changed in DomainModel, the same version is in Services.Implementation.SomeFancyMessagingLibrary. If our applications needs update of our internal packages all dependencies are updated to the same version.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)