简体   繁体   中英

MSBuild: Remove Reference to Assembly added via NuGet

In the process of moving some legacy code from packages.config to PackageReference.

I have a NuGet package (let's say A.nupkg) that has a reference to a different NuPkg (B.nupkg). B.nupkg includes a reference to Foo.dll.

A project referenced A.nupkg in packages.config, but B.nupkg was not (despite being a transitive dependency). The problem is that the project references a drop-in replacement (same namespace and classes, but including bug fixes) for the Foo API in the form of a Foov2.dll

Now with the change to PackageReference the transitive dependency is picked up, Foo.dll is referenced by the project and we end up with ambiguous references between Foo.dll and Foov2.dll. I can't change the NuGet package (wish I could) so I need a workaround.

I tried adding a target that removes the unwanted reference before building it, but I can't find the right spot to put it - or maybe references from NuGets are handled different to normal references:

  <Target Name="RemoveOutdatedReferences" BeforeTargets="BeforeBuild">
    <Message Importance="High" Text="All references: @(Reference->'%(FileName)'). 
           Sadly no Foo.dll so no wonder I can't remove it."/>
    <ItemGroup>
      <Reference Remove="Foo, Version=1.2.3.4, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb" />
    </ItemGroup>
  </Target>

Alternatively I also tried to remove the whole transitive NuGet package, but using <PackageReference Remove="Foo"/> didn't work either.

It appears like PackageReference Alias feature is designed specifically for scenarios of namespace collisions.

https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#packagereference-aliases

In some rare instances different packages will contain classes in the same namespace. Starting with NuGet 5.7 & Visual Studio 2019 Update 7, equivalent to ProjectReference, PackageReference supports Aliases. By default no aliases are provided. When an alias is specified, all assemblies coming from the annotated package with need to be referenced with an alias.

According to our little discussion, the only option so far I see is to create a custom NuGet package which encapsulates A.nupkg without its dependencies:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <PackageId>My.Wrapper.Around.A<PackageId>
    <PackageVersion>1.0.0<PackageVersion>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="A" Version="x.y.z">
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>
</Project>

According to the Microsoft docs , <PrivateAssets>all</PrivateAssets> should prevent all transitive dependencies from A.nupkg flowing up to the consumer.

And in your target project:

<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <PackageReference Include="My.Wrapper.Around.A" Version="1.0.0" />
    <PackageReference Include="Foov2" Version="1.0.0" />
  </ItemGroup>
</Project>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM