19

While developing a sample web app in .NET Core 1.1 and Visual Studio 2017 RC, I realized the following:

enter image description here

As you can see:

  • ClassLibrary3 has a reference to ClassLibrary2,
  • and ClassLibrary2 has a reference to ClassLibrary1

I wrote a simple method in class Class3 of ClassLibrary3 project, and the Intellisense allowed me to use Class1 just writing the name of the class, I mean, without doing an explicit reference to ClassLibrary1 project.

Am I missing some point here? I don't want somebody simply comes and overlooks ClassLibrary2.

Thanks.

Franco
  • 479
  • 3
  • 11
  • ClassLibrary1 is included in ClassLibrary3 due to the fact that it is needed by ClassLibrary2, so of course Class1 is available there. You just need to add `using ClassLibrary` as it says. You may need to clarify what your goal is - what are you trying to achieve? – Mitch Feb 24 '17 at 02:44
  • 4
    Well, I can't remember if previous versions of Visual Studio/.NET worked like that. I think it was mandatory to reference directly a project to be able to use its elements, not just having a transitive reference. – Franco Feb 24 '17 at 03:43
  • I found a possible solution for this question: https://ardalis.com/avoid-referencing-infrastructure-in-visual-studio-solutions – Franco Nov 20 '17 at 23:37
  • 1
    .NET Framework projects do not work like this. In .NET Framework, if A references B and B references C, that doesn't mean A references C. They changed this in .NET Core projects. I don't like this because A may not want to use C. The other day, a coworker accidentally used an extension method in a NuGet package that his project **did not** reference, a method named after something in Linq.Enumerable. ReSharper offered to "import missing references in file" so the coworker never saw the unexpected namespace. Plus, in theory, A's build can break if C creates a name collision somewhere. – Qwertie Mar 25 '20 at 20:03

3 Answers3

11

Transitive project-to-project references are a new feature of Visual Studio 2017 and Microsoft.NET.Sdk. This is intentional behavior.

See https://github.com/dotnet/sdk/issues/200.

natemcmaster
  • 25,673
  • 6
  • 78
  • 100
  • Nice. I suppose that now it will be more clear the dependency that UI layers have on Data layers in traditional 3-layered architectures. – Franco Feb 24 '17 at 13:36
  • How is a UI supposed to get access to data if it doesn't at some point have a dependency on the data layer? – Jez Nov 16 '20 at 12:00
11

If you're interested in disabling the transitive reference behavior, I finally found a way.

If you want Project A to reference B and B to reference C, but don't want A to reference C, you can add PrivateAssets="All" to B's ProjectReference to C, like so:

In B.csproj

<ItemGroup>
  <ProjectReference Include="..\C\C.csproj" PrivateAssets="All" />
</ItemGroup>

This setting makes C's reference private so it only exists within B. Now projects that reference B will no longer also reference C.

Source: https://github.com/dotnet/project-system/issues/2313

levihassel
  • 356
  • 4
  • 11
2

You have two options.

  1. In ClassLibrary1.csproj use DisableTransitiveProjectReferences property

    <Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
            <TargetFramework>netcoreapp3.1</TargetFramework>
            <DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences>
        </PropertyGroup>
        <ItemGroup>
            <ProjectReference Include="..\ClassLibraryCore2\ClassLibraryCore2.csproj" />
        </ItemGroup>
    </Project>
    
  2. In ClassLibrary2.csproj use PrivateAssets="All"

    <Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
            <TargetFramework>netcoreapp3.1</TargetFramework>
        </PropertyGroup>
        <ItemGroup>
            <ProjectReference Include="..\ClassLibraryCore3\ClassLibraryCore3.csproj" 
                PrivateAssets="All" />
        </ItemGroup>
    </Project>
    

I explained the difference more in other answer.

Mariusz Pawelski
  • 25,983
  • 11
  • 67
  • 80