如何设置 NuGet 包以将内容文件复制到输出构建目录?

How to setup a NuGet package to copy content files to output build directory?

NOTE: follow up from this question (now closed), as that one was too broad in scope, and the first part of that question, regarding .dlls, has been resolved, and this is a separate issue.

我正在开发一个 .NET Standard 2.0 project called ComputeSharp,我想将其发布为 NuGet 包,但我不知道如何让包将内容文件复制到的输出构建目录使用它的项目。一些信息:

<?xml version="1.0"?>
<package >
  <metadata>
    <id>ComputeSharp</id>
    ...
    <dependencies>
      <dependency id="SharpDX.Direct3D12" version="4.2.1-beta0-gab36f12303" />
      ...
    </dependencies>
    <contentFiles>
      <files include="..\ComputeSharp.Shaders\Renderer\Templates\*.mustache" buildAction="Content" copyToOutput="true" />
    </contentFiles>
  </metadata>
</package>
nuget pack ComputeSharp.csproj -Prop Configuration=Release -IncludeReferencedProjects
ComputeSharp.x.x.x.nupkg
├───rels
│   └───...
├───content
│   └───Renderer
│       └───Templates
│           └───ShaderTemplate.mustache
├───lib
│   └───netstandard2.0
│       ├───ComputeSharp.dll
│       ├───ComputeSharp.Graphics.dll
│       └───ComputeSharp.Shaders.dll
├───package
│   └───...
├───[Content_Types].xml
└───ComputeSharp.nuspec

PROBLEM: once I create a test project and install the NuGet package, I can build it just fine, but the whole Renderer\Templates\ShaderTemplate.mustache tree is not copied in the build directory, so as a result my lib can't load that file (as it's loaded relative to the path of the lib assembly).

我已经阅读了无数 SO 问题和文档,并在这里尝试了一堆组合(例如设置 ContentType="None" 而不是 "Content",但结果总是一样的: .mustache 文件存在于包中,但未将其复制到使用它的项目的构建目录中。我还需要做些什么才能让 NuGet 包在输出目录中重新创建该树 + 文件,什么时候建项目?

感谢您的帮助!

我建议使用构建操作将您需要的文件嵌入到程序集中 "Embedded resource"。这样你就不必依赖 Nuget 来安装它们。相反,在第一次使用时,您可以从程序集中读取它们并将它们复制到文件系统或直接使用它们。以下是如何从程序集中读取嵌入文件并将其复制到文件系统中:

private void CopyEmbeddedResourceToFile(Assembly assembly, string resourceName, string filePath)
{
        var key = GetResourceKey(assembly, resourceName);
        using (Stream stream = assembly.GetManifestResourceStream(key))
        using (var file = new FileStream(filePath, FileMode.Create))
        {
            if (stream == null)
                throw new ArgumentException($"Resource name '{resourceName}' not found!");
            stream.CopyTo(file);
        }
}

您想使用 contentFiles 文件夹而不是 content。请参阅此博客 NuGet ContentFiles Demystified

您还可以阅读 Enable support for 'content' folder with PackageReference,其中解释了为什么 content 文件夹不适用于 PackageReference