Reputation: 506
I am migrating an old style MsBuild csproj project to using PackageReference format and have run into a problem with transitive dependencies.
Consider the following Project A reference NuGet package B and C, each containing one single assembly using PackageReference. On Build Project A uses IL merge to incorporate B as public symbols in the A assembly and C as internalized symbols. Project D have a project reference to A.
The transitive dependencies case D to reference A, B and C. When building D, compile errors of the type error CS0433: The type 'X' exists in both 'A' and 'B' occur.
Is there any way to force D to not add an explicit reference to B or C in the scenario above?
Upvotes: 11
Views: 9426
Reputation: 1032
I was looking for this too and this answer kept popping up in google searches, but it didn't have the solution I know off (but can never remember), so I'll add my answer for future reference.
PrivateAssets
can be used to hide many things, but hiding all
is a bad move imo. You want some assets to move transitively, for example, for your app to run after a dotnet publish
, you'll need the assemblies you need, at runtime. Hiding all
assets means that when publishing, you may miss a few critical things - similar to deleting some files from the output.
From reading MS docs on the subject, I think what I want to hide, in order to not transitively be able to compile up against an assembly (but still have it at runtime), is compile
. So I'll set my PrivateAssets
to contentfiles;analyzers;build;compile
. This should mean that if MyLibraryB
depends on NugetPackageA
- then MyAppC
depending on MyLibraryB
will be able to run and publish correctly, without being able to use any classes or code from NugetPackageA
.
Note: This of course means that MyLibraryB
must not expose any public API that uses types found in NugetPackageA
. The consumer won't be able to use those public API's, at least not without themselves also referencing NugetPackageA
.
Upvotes: 2
Reputation: 506
I ended up using a workaround to move the transitive dependency to an alias to get around the compiler error.
<Target Name="ChangeAliasesOfBNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
<ItemGroup>
<ReferencePath Condition="'%(FileName)' == 'B'">
<Aliases>nonmerged</Aliases>
</ReferencePath>
</ItemGroup>
</Target>
I tried to use private assets but couldn't get the compiler error to go away in that way.
Upvotes: 7
Reputation: 76720
Disable transitive PackageReference dependency for a specific MsBuild project
If I understand you correct, you can try to use property <PrivateAssets>all</PrivateAssets>
or PrivateAssets="all"
for the PackageReference
. If you have a package that's marked with private assets it merely prevents it from flowing to parent project or getting packed.
<PackageReference Include="B" Version="1.0.0" PrivateAssets="all">
<PackageReference Include="C" Version="1.0.0" PrivateAssets="all">
You can check the document Controlling dependency assets and this thread for some details.
Hope this helps.
Upvotes: 4