【问题标题】:how reference file published with build action content参考文件如何与构建操作内容一起发布
【发布时间】:2019-05-17 04:54:02
【问题描述】:

我有一个需要加载一些 yaml 资源才能工作的 c# 项目,我已将它们设置为 "build action":"content" 和 "copy to Output directory":"Copy if newer"

为了加载它们,我只使用了一个相对路径,并且在项目中一切正常。

我实现了加载库的 xunit 项目,并且一切正常。

现在我在 nuget 上发布了该库,并尝试在 Asp.Net Core 上进行引用,但是当我尝试加载我的文件时,应用程序会尝试在错误的文件夹中找到它们:

从根 asp.net 项目的相对路径中搜索文件,但文件位于 C:\Users\[name]\.nuget\packages\[pakage name]\[version]\content

所以我想知道如何在 C# 中获取程序集的“内容”文件夹?

更新:我试着解释得更好

我有一个 Visual Studio 解决方案,我们称之为 foo.sln 和一个 C# 项目,我们称之为 foo.csproj

该项目是一个 netstandard 2.0 库,旨在供其他应用程序使用:cli、asp.net、core、wpf 等...

该库是为多平台构建的,因此可以在 Windows、Mac 和 Linux 上运行

在 foo 项目的根目录下有一个文件夹,我们称之为YamlDefinitions 在该文件夹中,我们有很多 .yaml 文件需要由我的 foo 库加载和解析。

所以foo.csproj 有类似的东西:

<Content Include="YamlDefinitions\Definition1.yaml">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitions\Definition2.yaml">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitions\Definition3.yaml">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitions\Definition4.yaml">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

这些文件是不可变的,所以我将它们作为内容而不是作为资源加载

现在在我的 foo 库的 c# 代码中,我有:

var filePaths = Directory.GetFiles("YamlDefinitions", "*.yaml", SearchOption.TopDirectoryOnly)

foreach (var filePath in filePaths)
{
     using (var reader = new StreamReader(filePath))
     {
          // Load the stream
          var yamlStream = new YamlStream();
          yamlStream.Load(reader);
          yaml = yamlStream.Documents.FirstOrDefault();
     }
}

该代码搜索、加载和解析所有可以在指定文件夹中找到的 yaml 文件。

一切似乎都还好,所以现在为了测试我在foo.sln 中创建了一个xunit 项目,我们称之为footest.csproj

现在我在footest.csproj 中引用foo.csproj

<ProjectReference Include="..\Foo\foo.csproj" />

所有测试都通过了,所以我打包了库并发布了 nuget 包:foo.nuget

现在我想尝试使用我的 nuget 包,所以我用 Net Core 2.2 创建了一个新的控制台应用程序,我们称之为MyConsoleApp.csproj

我安装了我的 nuget 包 foo.nuget:

 <PackageReference Include="Foo" Version="1.0.0"/>

包安装完毕,所有yaml文件都放在

C:\Users\UserName\\.nuget\packages\Foo\1.0.0\content\YamlDefinitions

C:\Users\UserName\\.nuget\packages\Foo\1.0.0\contentFiles\any\netstandard2.0\YamlDefinitions

这些文件在 MyConsoleApp.csproj 中也作为链接文件可见,但它们实际上并不存在于项目中。

现在我启动我的 MyConsoleApp.exe, 并收到错误,因为它无法找到这些 yaml 文件,因为应用程序试图将它们加载到与 MyConsoleApp.exe 相同的路径中

解决方法:从 Visual Studio 中,我选择链接在 MyConsoleApp.csproj 内的所有 yaml 文件,并将其设置为 CopyIfNewer

现在在 cproj Visual Studio 内部添加了这些代码行:

<Content Include="C:\Users\User\.nuget\packages\Foo\1.0.0\contentFiles\any\netstandard2.0\YamlDefinitions\Definition1.yaml">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>

我再次运行MyConsoleApp.exe,一切正常。

这种解决方法很糟糕,因为最终用户应该能够使用 nuget 库而无需手动指定复制文件。 如果我发布包含新定义的库的新版本,最终用户不应该知道这些必须包含在项目中。

不管怎样,还有一个更大的问题:

我创建了一个新的 ASP.NET Core 2.2 MVC 应用程序,我们称之为MyWebApp.csproj

我安装了Foo.nuget 并尝试使用它。

我手动设置复制输出文件夹中的所有 Yaml 定义,当我构建它们时,它们会自动复制到 MyWebApp\bin\Release\netcoreapp2.2\YamlDefinitions

我启动 web 应用程序,但我再次收到错误,因为我的 foo libray 试图在 MyWebApp\YamlDefinitions 中查找文件,但文件在 bin 文件夹中,所以没有任何效果。

如何修复我的库并以所有消费者应用程序都可以使用的方式发布为 nuget?

【问题讨论】:

  • @HGSandhagen 对不起,我不明白,我的文件在 nuget 中正确打包,是的,它们没有复制到 bin 目录中,但我不在乎它们在哪里,我只需要一种方法引用它们。我想避免在 nuspec 中为它们中的每一个指定一个输出目录,它们确实是很多文件。我需要一个返回我的 C# 函数:“C:\Users[name].nuget\packages[pakage name][version]\content”
  • 恐怕这行不通,因为 nuget 包是在构建磁贴处下载的。当您在目标系统上安装应用程序时,它们将不存在。
  • @H.G. Sandhagen 很抱歉,但我仍然不明白。这些文件由 nuget 库使用,而不是由目标应用程序使用。我需要图书馆能够读取它需要的文件。当您下载 nuget 包时,您还下载了内容文件,只是它们与程序集 dll 不在同一目录中,所以我不能使用相对路径。如果我不能使用相对路径,因为 nuget 将文件放在它想要的位置,我需要一个 C# 函数来检索它们。
  • 可能我没理解对。如果我错了,请纠正我。您创建了一个需要一些配置文件才能运行的库。该库需要输出文件夹(可执行文件的文件夹)中的文件。然后从这个库创建一个 nuget 包,并在 ASP.NET Core 应用程序中引用这个包。然后 nuget 包负责将包中的所有内容复制到引用应用程序的文件夹树中。我以前没有这样做,但我知道有办法做到这一点。

标签: c# path directory resources nuget


【解决方案1】:

我找不到用于检索存储内容文件的 nuget 文件夹的 C# 函数,我怀疑它是否存在,但我找到了这种工作方法:

foo.csproj 文件中,您需要指定每个文件应复制到输出文件夹中,这可以通过以下方式完成:

<Content Include="YamlDefinitions\Definition1.yaml">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <PackageCopyToOutput>true</PackageCopyToOutput>
</Content>

您需要添加 PackageCopyToOutput 才能使用 nuget,不幸的是,这无法通过 Visual Studio UI 完成,您必须手动编辑 .csproj

在 C# 中,您必须使用绝对路径,因为相对路径在所有类型的应用程序中都不相同(在 .NET cli 中与 ASP.NET 不同)

所以你必须使用这样的代码:

var directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "YamlDefinitions");
var filePaths = Directory.GetFiles(directory, "*.yaml", SearchOption.TopDirectoryOnly)

其中AppDomain.CurrentDomain.BaseDirectory返回复制内容文件的输出目录

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-10
    • 2015-03-20
    • 2015-10-01
    • 2014-07-25
    • 1970-01-01
    • 1970-01-01
    • 2017-11-20
    相关资源
    最近更新 更多