DEV Community

Cover image for DevLog 20250706: Analyzing Project Dependencies

DevLog 20250706: Analyzing Project Dependencies

When a code project grows complex it's going to be difficult to understand which depends on which - developers familiar with the C# ecosystem can look at NuGet Package Manager and use .csproj to try to study things but when the hierarchy gets complex it can feel inconvenient.

For instance, say I have a top-level entry program that I know ultimately depends on Mathnet.Numerics - now I need to figure out which subproject references it.

The General Approach

To view which project depend on which package in C#, below are some approaches using existing tools.

1. Using the .NET CLI

This approach only shows the NuGet packages the projects depend on.

a) List packages per project

Run, for each project:

dotnet list path/to/MyProject.csproj package
Enter fullscreen mode Exit fullscreen mode

We'll get an "Installed" section showing direct references.

b) Include transitive dependencies

dotnet list path/to/MyProject.csproj package --include-transitive
Enter fullscreen mode Exit fullscreen mode

This will also show packages pulled in by other packages.

c) Script it for the entire solution

On bash (Linux/macOS/git-bash):

for proj in $(find . -name '*.csproj'); do
  echo "== $proj =="  
  dotnet list "$proj" package --include-transitive | grep MathNet.Numerics -B2 -A2
done
Enter fullscreen mode Exit fullscreen mode

On PowerShell (Windows):

Get-ChildItem -Recurse -Filter *.csproj |
  ForEach-Object {
    Write-Host "== $($_.FullName) =="
    dotnet list $_.FullName package --include-transitive |
      Select-String "MathNet.Numerics" -Context 2,2
  }
Enter fullscreen mode Exit fullscreen mode

2. Grep / Select-String on .csproj files

Since NuGet package references live in <PackageReference> items, we can search directly:

  • bash:
  grep -R "PackageReference.*MathNet\.Numerics" -n .
Enter fullscreen mode Exit fullscreen mode
  • PowerShell:
  Get-ChildItem -Path . -Filter *.csproj -Recurse | Select-String -Pattern 'MathNet\.Numerics' -List

  # Or
  Get-ChildItem -Recurse -Filter *.csproj | Select-String -SimpleMatch 'MathNet.Numerics' -List
Enter fullscreen mode Exit fullscreen mode

That will show us exactly which project files reference it.

Alternatively, just do a full text search in VS Code with file type filter.

Search in VS Code

3. Visual Studio / Rider UI

  1. Right-click on the SolutionManage NuGet Packages for Solution…
  2. Go to the Installed tab, find MathNet.Numerics in the left panel.
  3. On the right, we'll see checkboxes or project-scoped lists showing which projects have it installed.

Once again, this method doesn't show the complete picture or the hierarchy of dependencies.

Manage NuGets for Entire Solution

4. MSBuild Dependency Graph (advanced)

If we need to audit transitive and project-to-project dependencies in one go, we can generate a restore graph:

dotnet msbuild /t:GenerateRestoreGraphFile /p:RestoreGraphOutputPath=graph.dg
Enter fullscreen mode Exit fullscreen mode

This produce a fairly comprehensive output that contains absolute paths and a bit too much irrelevant information.

graph.dh

Then inspect graph.dg (JSON) for entries where "PackageId":"MathNet.Numerics" and note the "ProjectPath" fields.

Custom Tool

Above methods work but if you don't like the output format, CLI syntax, or just want something more straightforward - then it's time for a custom tool.

The C# Dependency Analyzer is a tool that can quickly help identify dependencies of a source code project. This is useful in identifying unwanted nuget dependencies from any given entry assembly. It is equivalent to manually searching through .csproj to find which projects depend on which and debug NuGet dependencies.

It can do those three things:

  1. Print an exhaustive dependency tree with a root node at each source project level down to all dependent projects and most importantly the root NuGets
  2. Given a single target project/nuget, prints a filtered tree of all projects that depend on that assembly
  3. Given a single target project/nuget and a source assembly, it prints the tree paths that lead from the source assembly to the target - showing clearly the path from the source assembly to the ultimate dependency.

Below is an example output with command: path --path <solution path> --source Transcriber --target SkiaSharp

Dependency look up

References

  • Methodox Dependency analyzer: visit Github

Top comments (0)