Zev*_*itz 1 .net nuget .net-core
我有一个带有一些 NuGet 依赖项的项目,使用PackageReference:
<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.19" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
我不希望将依赖项直接安装在bin\${buildConfiguration}\${framework}文件夹中(括号中的文件( )):
bin
Debug
net472
(MyLibrary.dll)
(Microsoft.CSharp.dll)
(Microsoft.Xaml.Behaviors.Wpf.dll)
Run Code Online (Sandbox Code Playgroud)
相反,我希望每个构建的依赖项都位于更深的子文件夹中,如下所示:
bin
Debug
net472
(MyLibrary.dll)
MyLibrary
(Microsoft.CSharp.dll)
(Microsoft.Xaml.Behaviors.Wpf.dll)
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用nuget.config文件来控制解决方案的包应下载到的位置,但 NuGet 依赖项的构建输出保持不变—— bin/release/framework 文件夹。
请注意,我想要的不仅仅是移动文件,这可以通过构建后步骤完成,并且不会很有用。我需要在构建时更改对依赖 DLL 的引用以引用子文件夹而不是根文件夹;所以我可以将根文件夹的全部内容作为一个整体复制到不同的位置,并且仍然可以工作。
MyLibrary.dll使用 SDK 格式的项目构建,该项目使用PackageReference; 它可以是 .NET Framework、.NET Core 或 .NET Standard。
我怎样才能做到这一点?
一些背景
我为表达式编写了一个 Visual Studio调试可视化工具。调试可视化工具是手动复制的单个 DLL - 连同它们的依赖项 - 到 Documents 下的特定子文件夹 - 例如Visual Studio 2019\Visualizers- 或到VisualizersVS 安装文件夹的子文件夹。
如果有两个可视化器依赖于同一个库的不同版本,那么一个很容易被破坏。删除可视化工具是删除不需要的依赖项的事。
在为 .NET Core 或 .NET Standard 编写可视化工具时,需要创建多个 DLL 使情况更加复杂;每个 DLL 可能都有自己的依赖项。
如果可以将依赖项输出到具有相同名称的子文件夹,那将是朝着正确方向迈出的一步。
(开发人员社区功能请求和(现已关闭)请求记录此问题的更好解决方案)
我只在最基本的场景中测试过这个,所以也许多目标项目需要对此进行修改,并且非 sdk 风格的项目可能与 sdk 风格的项目不同,但是:
在调查任何 MSBuild 时,您需要了解的最重要的一点是二进制日志输出,可以使用MSBuild 结构化日志查看器查看。
所以,我运行了dotnet new console, 和dotnet add package NuGet.Versioning,因为我真的需要在控制台应用程序中进行 SemVer2 比较。现在,我跑dotnet build -bl和start msbuild.binlog。
在 MSBuild 日志查看器中,从包中搜索程序集名称和单词 copy。就我而言,我搜索了“copy nuget.versioning.dll”并找到了一个结果。单击它,我看到消息是由名为“Copy”的任务输出的,该任务在名为“_CopyFilesMarkedCopyLocal”的目标中运行。单击树中的 Task Copy,它会在运行 Copy 任务的行上打开 Microsoft.Common.CurrentVersion.targets 的文本视图,我看到:
<Copy
SourceFiles="@(ReferenceCopyLocalPaths)"
DestinationFiles="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyLocalIfPossible)"
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyLocalIfPossible)"
Condition="'$(UseCommonOutputDirectory)' != 'true'"
>
Run Code Online (Sandbox Code Playgroud)
注意目的地DestinationFiles="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')"。好的,DestinationSubDirectory听起来很有希望。检查复制任务的参数,DestinationFiles 项没有任何DestinationSubDirectory设置,所以看来我可以将它设置为我想要的任何相对路径。
让我们搜索ReferenceCopyLocalPaths项目的定义位置。我看到“AddItem ReferenceCopyLocalPaths”的两个搜索结果,但检查它们的“调用堆栈”,我看到它们都在名为“ResolveReferences”的目标下。
最后一件事,由于这个问题是关于来自 PackageReference 的程序集,我想格外小心,所以我查看了 ReferenceCopyLocalPaths 项,并注意到它有一个名为 NuGetPackageId 的元数据项。
所以现在:
将此目标添加到您的 csproj 中:
<Target Name="CopyPackageAssembliesToSubFolder" AfterTargets="ResolveReferences">
<ItemGroup>
<ReferenceCopyLocalPaths Condition=" '%(ReferenceCopyLocalPaths.NuGetPackageId)' != '' "
Update="%(ReferenceCopyLocalPaths)"
DestinationSubDirectory="libs\" />
</ItemGroup>
</Target>
Run Code Online (Sandbox Code Playgroud)
现在,当我运行时dotnet clean ; dotnet build,我看到 bin 目录中有一个libs/包含 NuGet.Versioning.dll的文件夹。
| 归档时间: |
|
| 查看次数: |
708 次 |
| 最近记录: |