参考文件如何与构建操作内容一起发布

时间:2018-12-16 17:34:32

标签: c# path directory resources nuget

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

要加载它们,我仅使用一个相对路径,并且一切都在项目中起作用。

我意识到xunit项目可以加载库,并且一切仍然正常。

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

从根asp.net项目的相对路径搜索文件,但文件位于C:\ Users \ [名称] \。nuget \ packages \ [文件名] \ [版本] \内容

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

更新:我试图更好地解释

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

该项目是一个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

现在我在foo.csproj内引用footest.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?

1 个答案:

答案 0 :(得分:0)

我找不到C#函数来检索存储内容文件的nuget文件夹,并且我怀疑是否存在,但是我找到了这种可行的方法:

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返回在其中复制内容文件的输出目录

相关问题