在 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。只需将TargetsForTfmSpecificBuildOutputTarget 节点添加到您的.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 文件]的主要内容,如果未能解决你的问题,请参考以下文章

如何使我的托管 NuGet 包支持 C++/CLI 项目?

如何正确引用nuget包,这样就不会对路径进行硬编码

NuGet:将包依赖项显式列出为项目中的包引用,以便可以卸载它们

在哪里放置以及如何在 c++ 项目中包含 dll 文件?

C#在我的项目中包含引用dll

使用visual studio pack在nuget包中包含构建目录