Search code examples
c#server-side.net-5circular-dependencyblazor-webassembly

Circular Dependency in my .NET 5.0 C# project - how can I solve it?


I have the following project structure with following namespaces:

  • Solution: ProjectName
    • SubProject: ProjectName.Shared
      • Contains Namespace: ProjectName.Shared.Logging
    • SubProject: ProjectName.DbContext
      • Has project reference: ProjectName.Shared
      • Uses Namespace: ProjectName.Shared.Logging

The DbContext project is currently using a project reference to the Shared project because we would like to log data via a solution-wide used Logger.

Now it shall be changed so that the Logger shall also write in some database. It would mean to me that it would become a circular project dependency if I try to add ProjectName.DbContext as a project reference in ProjectName.Shared.

It would look like this then:

  • Solution: ProjectName
    • SubProject: ProjectName.Shared
      • Contains Namespace: ProjectName.Shared.Logging
      • Has project reference: ProjectName.DbContext
      • Uses Namespace: ProjectName.DbContext
    • SubProject: ProjectName.DbContext
      • Has project reference: ProjectName.Shared
      • Uses Namespace: ProjectName.Shared.Logging

I was considering creating a new SubProject called ProjectName.Logging, but I could not see how it would solve my circular dependency problem; ProjectName.Logging would need ProjectName.DbContext and the other way around, too.

Does someone have an idea how to solve that circular dependency?


Solution

  • four options:

    1. combine the ProjectName.Shared and ProjectName.DbContext assemblies
    2. see whether one of them could declare an interface - perhaps ProjectName.DbContext could declare and accept an IDbLogger interface, which is then implemented in ProjectName.Shared and passed in, so it can do logging without having to know the details
    3. create an additional package underneath which has the logging abstractions, which both ProjectName.Shared and ProjectName.DbContext would reference
    4. like 3, but using the pre-rolled ILogger[<T>] from Microsoft.Extensions.Logging.Abstractions

    (it is also technically possible to create a genuinely circular build, but it is horribly complicated, very brittle, and you should not consider it as anything other than a hack of absolute last resort)