在 nuget 包中包含引用的项目 DLL [.Net Core RC3 *.csproj 文件]
Posted
技术标签:
【中文标题】在 nuget 包中包含引用的项目 DLL [.Net Core RC3 *.csproj 文件]【英文标题】:Including referenced project DLLs in nuget package [.Net Core RC3 *.csproj file] 【发布时间】:2017-02-01 12:01:49 【问题描述】:我有一个包含两个项目的解决方案。第一个项目名为 Library1,它引用名为 Referencelibrary 的项目二。我正在尝试将 ReferenceLibrary 的 DLL 嵌入 Library1 的 nuget 包中,这样我就不必发布 2 个单独的 nuget 包。通过将以下条目添加到我的 csproj 文件中,我已经能够将 ReferenceLibrary 的 DLL 嵌入到 nuget 包中(看起来如此):
<ItemGroup>
<ProjectReference Include="..\ReferenceLibrary\ReferenceLibrary.csproj">
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<IncludeAssets>ReferenceLibrary.dll</IncludeAssets>
<IncludeAssets>ReferenceLibrary.pdp</IncludeAssets>
</ProjectReference>
</ItemGroup>
但是当我导入 nuget 包并尝试运行我的测试应用程序时,我得到以下异常:
我假设 DLL 已被嵌入,因为在将“IncludeAssets”添加到 csproj 之前,我无法导入 nuget 包,因为它试图引用 ReferenceLibrary nuget 包。但是在添加了这些条目之后,它允许我导入它。但现在它会在运行时爆炸。任何帮助将不胜感激。谢谢!
;)
【问题讨论】:
“这样我就不必发布 2 个单独的 nuget 包”:为什么这对您如此重要? 这个问题有什么更新吗?你能从 Leo 的建议中得到有用的信息吗? 您好 Jeroen,因为我通常对所有代码使用分层方法。我经常做的事情是将我的数据访问层与其他层分开。因此,在这种特殊情况下,我不想发布单独的存储库 nuget 包。 @Wendy - MSFT - 不是真的,即使在尝试了 Leo 的建议后,我仍然收到 System.IO.FileNotFoundException 错误消息。 【参考方案1】:现在描述了一个更新的解决方法here。只需将TargetsForTfmSpecificBuildOutput
和Target
节点添加到您的.csproj
文件中,如下所示。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" />
</ItemGroup>
</Target>
</Project>
pack 目标中这个扩展点的官方文档可以在here找到。
然后您可能还想将属性 PrivateAssets="All"
添加到 ProjectReference
元素以禁止该项目在生成的包中显示为 NuGet 依赖项,例如:
<ProjectReference Include="MyNonNugetDependentProject.csproj" PrivateAssets="All" />
【讨论】:
这可以很好地确保所需的 DLL 最终位于 nuget 包的 lib 文件夹中,但是现在在使用此包时,它会查找具有 DLL 名称的 nuget 包,而不是使用生成的那个。 @JustAnotherDeveloper 的原因是您的 DLL 仍然在打包过程中生成的 nuspec 文件中。要修复它,您必须将 PrivateAssets="all" 属性添加到您的项目引用中(请参阅 github bi 上的完整示例以及相关答案中的链接)。 谢谢!你为我节省了大量时间。 如果我有两个 ProjectReferences 并希望保留一个作为 nugget 引用并包含第二个呢?【参考方案2】:这似乎是 Visual Studio 2017 中核心项目的内置 NuGet 打包的一个已知限制,在此讨论:
https://github.com/NuGet/Home/issues/3891
在那个讨论线程中有一个对我有用的 hack:
https://github.com/NuGet/Home/issues/3891#issuecomment-309792369
<ItemGroup>
<_PackageFiles Include="$(OutputPath)\ReferencedProjectDll.dll">
<BuildAction>None</BuildAction>
<PackagePath>lib\net45\</PackagePath>
</_PackageFiles>
</ItemGroup>
请注意,您需要更改程序集名称,并且您可能还需要更改包路径以匹配您正在使用的 .NET Framework 版本。以上示例适用于 4.5,但您可能使用的是更新的 4.6。
【讨论】:
现在在 GitHub 上针对该问题评论了一个更新的解决方法,我已将其作为答案发布here。【参考方案3】:我们无法将引用的项目 DLL 包含在三个或以上项目中。
例如,当项目 Library1 引用项目 ReferenceLibrary 时,ReferenceLibrary.dll 将被添加到 Library1 的引用中。但是,当您将项目 Library1 引用到项目测试应用程序时,只会将 Library1.dll 添加到测试应用程序项目的引用中。引用的项目 DLL “Referencelibrary”将被省略。详情请参阅Flexible Project-to-Project References。
如果您想在 Library1 的 nuget 包中嵌入 ReferenceLibrary 的 DLL 并将其引用到测试应用项目,您可以在添加参考项目 Library1 后将 ReferenceLibrary 项目引用添加到测试应用项目 或将 ReferenceLibrary.dll 设置为 Library1 项目的依赖项,您可以将以下条目添加到 Library1.csproj 中,然后将 Library1 打包并通过 NuGet 安装此包以测试应用程序:
<ItemGroup>
<Reference Include="ReferenceLibrary, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ReferenceLibrary.1.0.0\lib\net461\ReferenceLibrary.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
更新:
如果我们想在 Library1 的 nuget 包中嵌入 ReferenceLibrary 的 DLL,无论我们如何嵌入 DLL,我们都应该确保 ReferenceLibrary.dll 包含在 Library1 包中。因此,当我们打包 Library1 包并将目标设置为 lib 文件夹时,您可以将 ReferenceLibrary.dll 作为文件添加到 Library1.nuspec。下面是我的 Library1.nuspec:
<?xml version="1.0"?>
<package >
<metadata>
<id>Library1</id>
<version>1.0.0</version>
<authors>xxxx</authors>
<owners>xxxx</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package description</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>Copyright 2017</copyright>
<tags>Test</tags>
</metadata>
<files>
<file src="..\Library1\bin\Debug\Referencelibrary.dll" target="\lib\net461" />
<file src="..\Library1\bin\Debug\Library1.dll" target="\lib\net461" />
</files>
</package>
请注意:您还需要在 Library1.nuspec 中包含 Library1.dll。
【讨论】:
嗨,Leo,感谢您的回复。我今天晚些时候回家时必须检查一下。 ;) 我尝试使用上面的 HintPath,但我仍然得到与运行 .Net Core 控制台应用程序时相同的 System.IO.FileNotFoundException。 :( @Zorthgo,我已经更新了上面的答案,请在有空时检查一下。如果您对此有任何更新,请告诉我。希望对您有所帮助。 感谢您的更新。我回家后会试试这个。一个问题。您提到了一个 .nuspec 文件,在示例中,目标设置为“\lib\net461”。我计划创建 .Net 标准库。因此,包信息嵌入在 .csproj 文件中,不再存在于单独的 .nuspec 文件中。上述方法是否也适用于新的“dotnet pack”命令?谢谢! @Zorthgo,根据这篇文章和我自己的测试:github.com/dotnet/cli/issues/2170,不支持 nupsec 文件的“dotnet pack”。所以我建议你使用“nuget pack”命令创建.Net标准库,详情请参考docs.microsoft.com/en-us/nuget/guides/…。【参考方案4】:为了将 DLL 放置在我选择的文件夹中,我使用了 at Microsoft 所述的其他自定义点。
所以我最终得到了以下结果:
<PropertyGroup>
<IncludeBuildOutput>false</IncludeBuildOutput> <!-- omit the package creating library itself -->
<PackProject>true</PackProject>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);CreatePackNupkg</TargetsForTfmSpecificContentInPackage>
</PropertyGroup>
<Target Name="CreatePackNupkg">
<ItemGroup>
<TfmSpecificPackageFile Include="$(OutputPath)\<whatever>.*.dll">
<PackagePath>folder/subfolder</PackagePath>
</TfmSpecificPackageFile>
</ItemGroup>
</Target>
NuGet.Pack 包的创建方式相同 (have a look)。
【讨论】:
以上是关于在 nuget 包中包含引用的项目 DLL [.Net Core RC3 *.csproj 文件]的主要内容,如果未能解决你的问题,请参考以下文章