如何在构建期间控制 nuget 包依赖项的输出

How to control output of a nuget package dependencies during build

我想在我的应用程序中支持向后兼容性。 简单地说 - 一个应用程序需要使用不同版本的 dll,具体取决于应用程序在运行时获得的标志。

我简化了所有内容并创建了一个包含 2 个项目的测试解决方案。 每个项目都有自己的相同 nuget 包版本。

我选择了 System.Drawing.Common 因为它没有依赖关系。

ClassLibrary1 包含 System.Drawing.Common 版本 4.5.0

ClassLibrary2 包含 System.Drawing.Common 版本 6.0.0

两个项目有相同的输出路径:

<OutputPath>..\DEBUG\</OutputPath>

当我构建解决方案时,我的输出文件夹中只有一个 System.Drawing.Common.dll

因为两个 dll 同名,只是版本不同。

下图所需的行为:

  1. 根据版本将nuget包依赖分发到不同的文件夹中。

  2. 根据版本给nuget包依赖加上后缀。

这个想法是控制 nuget 包依赖项的输出。 你知道我该如何实现吗?

P.S。所有其他逻辑 - 根据版本等解决依赖关系超出了这个问题的范围。

这不是包解析在 .NET 中的工作方式,您会得到每个包的一个版本,这是在恢复时决定的。

如果您有一个非常小众的问题,可能会有一些时髦的选择,但听起来您可能正在尝试以一种不常见的方式解决一个常见问题,这通常不是一个好主意。

通常,对于向后兼容性问题,责任在于图书馆的出版商而不是图书馆的消费者,以通过不进行重大 API 更改来确保一切正常。

这是可能的。 首先,您需要将 GeneratePathProperty 添加到 csproj 文件

中的 PackageReference 元素
<ItemGroup>
    <PackageReference Include="System.Drawing.Common">
        <Version>4.5.0</Version>
        <GeneratePathProperty>true</GeneratePathProperty>
    </PackageReference>
</ItemGroup>

它允许我们使用包含 nuget 包路径的 $(PkgSystem_Drawing_Common) 变量。

然后我们需要创建一个msbuild targets文件

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="CopyNugetDll" BeforeTargets="BeforeCompile" Outputs="System.Drawing.Common.dll">
        <XmlPeek XmlInputPath="$(ProjectPath)" Query="Project/ItemGroup/PackageReference[@Include='System.Drawing.Common']/Version/text()">
            <Output TaskParameter="Result" PropertyName="NugetPackageVersion" />
        </XmlPeek>
        <ItemGroup>
            <NugetrDll Include="$(PkgSystem_Drawing_Common)\lib\net461\System.Drawing.Common.dll" />
        </ItemGroup>
        <Message Text="Copying @(NugetrDll) to $(OutDir)" Importance="high" />
        
        <Exec Command="copy $(PkgSystem_Drawing_Common)\lib\net461\System.Drawing.Common.dll $(OutDir)\System.Drawing.Common.$(NugetPackageVersion).dll" />
    </Target>
</Project>

这里使用 xpath 我们从 project.assets.json 文件 select 版本并将其保存在 NugetPackageVersion 变量中。 Exec copy 用于将 dll 复制到具有特定前缀的特定位置,该前缀包含来自 NugetPackageVersion 变量的值。

最后您需要将 msbuild targets 文件包含到项目中

<Import Project="CopyDll.targets" />