24

How should I reference to another project A from project B in the same solution?
What do I gain and what do I lose if I:

  • Add the reference to project A as a project reference.
  • Install the NuGet package of project A in project B.

Things that would bother me are build dependencies, versioning..?
Or does this totally destroy the purpose of a solution?

grmbl
  • 2,514
  • 4
  • 29
  • 54
  • 1
    Project reference is a natural fit. What exactly is the problem you met? – Lex Li Jan 30 '18 at 17:04
  • Project vs package references and solution/repo separation is usually more aligned with how the versions and release cycles are managed and how the dev teams working on them are structured over technical necessities – Martin Ullrich Jan 30 '18 at 21:39

4 Answers4

22

Project reference VS NuGet

Project reference or NuGet is a very common problem in our development process, we need to choose which one to use based on our actual situation.

For example, if the referenced project A is modified frequently during the development process, we recommend to use Project reference. Because if you use nuget, you have to rebuild the referenced project, recreate the nuget package, reinstall that nuget package to the project B, even you have to publish it to the server. This will bring a lot of unnecessary work and we often forget to update our nuget package after we modify the referenced project A. If you use the project reference, you will not have these problems. The modified referenced project A will be update automatically before we build the project B.

On the other hand, when we share our referenced project A out of solution, or share that project to others, nuget will be a better choice. It has more portability.

So the project reference will be recommended when you reference to another project A from project B in the same solution, the nuget is more appropriate when share the reference project out of solution or share project to others.

Besides, there is a Visual Studio extension NuGet Reference Switcher, which which automatically switches NuGet assembly references to project references and vice-versa.

Hope this helps.

Leo Liu
  • 71,098
  • 10
  • 114
  • 135
16

With the first approach, you gain in simplicity, since you don't need to generate a new version of the ProjectA nuget package, every change you make in it (i.e. ProjectA.nupkg).

However, with the second approach, you gain in portability, since you can easily share the same nuget package with other projects / solutions.

Personally, I create nuget packages only for projects whose goal is to share with other solutions. (E.g. libs and frameworks).

Hope this helps you decide!

Maicon Heck
  • 2,017
  • 1
  • 20
  • 27
11

Nowadays with the new csproj format the you can use both at the same time (if you have both projects in the same solution).

In your example, you could reference project A from project B as a project reference. Then, if you want to release project A as a NuGet package you just need to add the following tag to it's csproj inside a PropertyGroup:

    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>

The plot twist: If you want to release project B as a NuGet Package too just add the GeneratePackageOnBuild target - MSBuild will set projectA.nupkg as a dependency in projectB.nupkg.

This way you can work internally with your projects while at the same time release them as packages to third parties or other teams.

Josef Ginerman
  • 1,460
  • 13
  • 24
  • You could do this with the old projects by using .nuspec files, when you publish a NuGet package, if a referenced project has a .nuspec file, it will automatically add it as a `NuGet` reference. – Michal Ciechan Jul 11 '19 at 21:26
  • What happens if you change project A but forget to publish a new version of it and then publish project B with code that depends on the new changes? – andre_ss6 Oct 16 '19 at 20:29
  • If both projects are in the same solution, you can perform the changes at the same time and publish them together. If you are only pushing projectB to your feed then it will reference a currently non-existing version of projectA package, so you need to make sure to publish them all together. NuGet packages require a good CI\CD process. – Josef Ginerman Oct 17 '19 at 07:33
  • You're describing something different. Generating a package is not the same as referencing a package. To be relevant to the question, `project A` would have to be able to reference `project B` and simultaneously reference `B.nupkg`. VS is a little flaky in this case -- if the NuGet ref is added second, it keeps the reference with a yellow warning symbol in Solution Explorer. If the project ref is added second, it unloads the conflicting NuGet package (silently, which is not ideal UX). – McGuireV10 Nov 05 '20 at 14:37
  • You're right in that it adds more than what the question asks. What my solution adds is the merge of both options: you can reference A as a project inside the solution, but if you were to publish B then A would automatically be referenced as a package. This is not the case when using the old csproj format, where the B package would just include all referenced binaries in its lib folder. – Josef Ginerman Nov 08 '20 at 09:54
1

You could use both: project references during development (faster), and package references during production.

In your .csproj project file:

<ItemGroup Condition="'$(Configuration)'=='Debug'">
  <ProjectReference Include="../../../Library1/Library1.csproj" />
  <ProjectReference Include="../../../Library2/Library2.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'!='Debug'">
  <PackageReference Include="Library1" Version="1.0.0" />
  <PackageReference Include="Library2" Version="1.0.0" />
</ItemGroup>

In development: project compiled in debug mode, so the project reference will be used.

In production (CI server, docker container): project compiled in release mode, so the package reference will be used.

lonix
  • 14,255
  • 23
  • 85
  • 176
  • That would work if your dependent projects are in the same repository (monorepo) I guess or you could git submodules but then how would you make sure that you are aligned with what is released? – grmbl Jul 16 '22 at 12:36
  • @grmbl I do this, and my dependencies are in *different monorepos*. (You could have them in the same monorepo too, if you want.) – lonix Jul 16 '22 at 12:40
  • Sorry if I gave the impression that was doubting it would work, I just found it an interesting approach. But I'm a bit worried to debug against a local project that might have differences to the released 1.0.0 version so I could release a locally working project but it will break when using the release packages 1.0.0. You could catch this (partially) during CI build of course but I wonder how you cope with that? – grmbl Jul 16 '22 at 12:46
  • @grmbl No worries, you uncovered an interesting scenario. But personally I haven't had that issue because once the latest commit lands on the CI server (or when built inside a container) it becomes a non-issue. It's a very convenient workflow. – lonix Jul 16 '22 at 12:59