我有一个c#项目,需要加载一些yaml资源才能工作,我用"构建操作":"内容"one_answers"复制到输出目录":"如果更新则复制"设置了它们
为了加载它们,我只使用一个相对路径,所有的东西都在项目中工作。
我实现了xunit项目,该项目加载了库,并且一切仍然正常。
现在我在nuget上发布了库,我正试图在Asp.Net Core上引用,但当我试图加载文件时,应用程序试图在错误的文件夹中找到它们:
这些文件是在根asp.net项目的相对路径中搜索的,但文件位于C:\Users\[name]\.nuget\packages\[package name]\[version]\content 中
所以我想知道如何在C#中获取程序集的"内容"文件夹?
更新:我试图更好地解释
我有一个visual studio解决方案,我们称之为foo.sln
,还有一个C#项目,我们称其为foo.csproj
该项目是一个网络标准2.0库,它被其他应用程序使用:cli、asp.net、core、wpf等
该库是为多平台构建的,因此可以在Windows、Mac和Linux 上运行
在foo项目的根目录中有一个文件夹,我们称之为YamlDefinitions
在这个文件夹中,我们有很多.yaml文件,这些文件需要由我的foo库加载和解析。
所以foo.csproj
有这样的东西:
<Content Include="YamlDefinitionsDefinition1.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitionsDefinition2.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitionsDefinition3.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitionsDefinition4.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="..Foofoo.csproj" />
所有测试都通过了,所以我打包了库并发布了nuget包:foo.nuget
现在我想尝试使用我的nuget包,所以我用Net Core 2.2创建了一个新的控制台应用程序,我们称之为MyConsoleApp.csproj
我安装我的nuget包foo.nuget
:
<PackageReference Include="Foo" Version="1.0.0"/>
软件包已安装,所有yaml文件都放置在中
C:UsersUserName\.nugetpackagesFoo1.0.0contentYamlDefinitions
和
C:UsersUserName\.nugetpackagesFoo1.0.0contentFilesanynetstandard2.0YamlDefinitions
这些文件在MyConsoleApp.csproj
中也作为链接文件可见,但它们在项目中并不存在。
现在我启动了MyConsoleApp.exe,
,但我遇到了一个错误,因为它无法找到这些yaml文件,因为应用程序试图将它们加载到与MyConsoleApp.exe
相同的路径中
解决方法:从visual studio中,我选择MyConsoleApp.csproj
中链接的所有yaml文件,并将其设置为CopyIfNewer
现在在cproj视觉工作室内添加以下代码行:
<Content Include="C:UsersUser.nugetpackagesFoo1.0.0contentFilesanynetstandard2.0YamlDefinitionsDefinition1.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
我再次运行MyConsoleApp.exe
,一切正常。
这种解决方法很糟糕,因为最终用户应该能够使用nuget库,而无需手动指定复制文件。如果我发布了包含新定义的库的新版本,那么最终用户不应该意识到这些定义必须包含在项目中。
无论如何,还有一个更大的问题:
我创建了一个新的ASP.NET Core 2.2 MVC应用程序,我们称之为MyWebApp.csproj
我安装了Foo.nuget
并尝试使用它。
我手动设置为复制输出文件夹中的所有Yaml定义,当我构建它们时,它们会自动复制到MyWebAppbinReleasenetcoreapp2.2YamlDefinitions
中
我启动了web应用程序,再次遇到错误,因为我的foo库试图在MyWebAppYamlDefinitions
中查找文件,但文件在bin文件夹中,所以什么都不起作用。
如何以所有消费者应用程序都可以使用的方式修复我的库并作为nuget发布?
我找不到一个C#函数来检索存储内容文件的nuget文件夹,我怀疑它是否存在,但我找到了这种工作方法:
在foo.csproj
文件中,您需要指定每个文件都应该复制到输出文件夹中,这可以使用来完成
<Content Include="YamlDefinitionsDefinition1.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
返回复制内容文件的输出目录