.Net Core 库中的嵌入式资源
Posted
技术标签:
【中文标题】.Net Core 库中的嵌入式资源【英文标题】:Embedded resource in .Net Core libraries 【发布时间】:2016-12-10 06:48:05 【问题描述】:我刚刚开始研究 .Net Core,但我没有看到经典资源和任何看起来像资源的东西。例如,在经典的 .Net 类库中,我可以将带有一些脚本的文本过滤器添加到我的项目中,然后我可以将这些文件添加到项目的资源中。之后,我可以通过以下方式轻松使用它:
Connection.Execure(Properties.Resources.MySuperScript);
我看到.Net Core 库中没有这样的功能,至少我没有看到。 .Net Core 中是否有替代方法可以将一些静态数据作为嵌入式资源存储在库中?如果存在,如何使用?
【问题讨论】:
尚不支持资源。也许使用 JSON 或 XML 文件? 我使用了 SQL 脚本的资源,它们包含引号等特殊符号,因此使用 JSON 并不方便,因为应该将这些符号更改为转义序列。以这种形式阅读和修复脚本并不舒适。 :( How do I make an XML file an embedded resource in a vNext (ASP.NET 5) class library?的可能重复 这个答案:***.com/a/57811919/156991 是今天的最佳答案。 【参考方案1】:更新:
.NET Core 1.1 及更高版本已删除 project.json
并返回到 .csproj
文件。
这改变了第 2 步,但并没有改变那么多。必要的行非常相似:
<ItemGroup>
<Content Remove="_fonts/OpenSans.ttf" />
<Content Remove="_fonts/OpenSans-Bold.ttf" />
<Content Remove="_fonts/OpenSans-Italic.ttf" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="_fonts/OpenSans.ttf" />
<EmbeddedResource Include="_fonts/OpenSans-Bold.ttf" />
<EmbeddedResource Include="_fonts/OpenSans-Italic.ttf" />
</ItemGroup>
可能有类似*.tff
的形式;未经证实。
步骤 1 和 3 不变。
要在 .NET Core 1.0 项目中使用嵌入式资源,请执行以下操作:
照常添加您的嵌入文件。
示例:名为“_fonts”的目录中的一些 FONT 文件
修改“project.json”以包含相关资源。
就我而言:
"buildOptions":
"embed":
"include": [
"_fonts/*.ttf"
]
,
在代码中访问嵌入的资源。
var assembly = typeof(MyLibrary.MyClass).GetTypeInfo().Assembly;
Stream resource = assembly.GetManifestResourceStream("MyLibrary._fonts.OpenSans.ttf");
关键是在GetManifestResourceStream
调用中使用正确的名称。你必须使用[assembly name].[directory].[file name]
。
【讨论】:
为确保获取正确的资源,请评估目标程序集中的所有可用资源string[] names = assembly.GetManifestResourceNames();
这对我有用,但最终仍然使用已执行程序集根目录中的文件路径。我有两个 dll,一个用于 API,一个用于 CSV。 API 是运行的库。 CSV 包含我需要阅读的文件。即使文件被列为“Mylibrary.folder.file”,即“CSV.csv.somefile.csv”,它也会尝试读取“solution/API/somefile.csv”。我希望它读取的路径是“solution/CSV/csv/somefile.csv”。关于如何在程序集中保留相对路径的任何建议?
感谢@Luka,您的评论帮助我识别了嵌入资源的实际名称!
@Zartag 所说的有意义,除了使用路径无法访问文件这一事实外,主要解决方案是可行的,但在某些用例中,像这样读取流是没有意义的
看起来资源名称的格式使用了程序集的默认命名空间,而不是程序集名称。不过,如上所述,仍然是点分隔的。【参考方案2】:
现在project.json
已被弃用,您必须在.csproj
文件中指定它。
<ItemGroup>
<EmbeddedResource Include="_fonts\*.ttf" />
</ItemGroup>
您可以使用如图所示的通配符,或者直接列出文件。
【讨论】:
如果没有事后如何获取数据的详细信息,这并没有多大用处。 编译后资源在磁盘的什么位置?我希望在 /bin 文件夹中的某处找到 *.ttf。 @JimAho 文件嵌入在程序集中。 @Brondahl 问题是关于嵌入资源的,这是如何做到的。 :) OP 可能知道从这里去哪里。对于其他寻找如何做到这一点的人,这里有一个与使用 xunit 进行测试相关的示例实现:patriksvensson.se/2017/11/… 来自 Johny 的链接不再有效,这是存档版本:web.archive.org/web/20201024173213/https://patriksvensson.se/…【参考方案3】:对于较新版本的 .Net Core - 2.0 或更高版本 - 有一个专门的类 EmbeddedFileProvider
可以抽象嵌入式文件读取。要使用它,请将Microsoft.Extensions.FileProviders.Embedded
包添加到您的应用程序中:
dotnet add package Microsoft.Extensions.FileProviders.Embedded
EmbeddedFileProvider
允许您创建流阅读器,并根据您的场景使用:
var embeddedProvider = new EmbeddedFileProvider(Assembly.GetExecutingAssembly());
using (var reader = embeddedProvider.GetFileInfo("yourfile.ext").CreateReadStream())
// some logic with stream reader
【讨论】:
这看起来很有希望,但我遇到了子文件夹中的文件问题。我最终使用 Luka 上面提到的string[] names = assembly.GetManifestResourceNames();
关闭了我自己的匹配逻辑。
GetFileInfo() 的文件格式是“Folder.filename.Extension”,没有命名空间。这与使用文件格式“Namespace.Folder.filename.Extension”的 assembly.GetManifestResourceStream() 不同,包括命名空间
我收到一个找不到资源错误。我将文件添加到图像然后将文件类型更改为嵌入。 var resourceName = "X_Signature.jpg";使用 (var stream = assembly.GetFileInfo(resourceName).CreateReadStream())
我将资源文件设置为嵌入式资源,并设置了自定义的namespace.resources【参考方案4】:
人们已经普遍回答了这个问题,所以这是一个简单的答案。
在使用以下内容之前,应将该文件作为嵌入资源添加到 .csproj / project.json
用法
var myJsonFile = ReadManifestData<Tests>("myJsonFile.json");
-
参数:嵌入文件名名称;类型:目标资源程序集中的任何类
查找具有该名称的嵌入式资源
返回字符串值
方法
public static string ReadManifestData<TSource>(string embeddedFileName) where TSource : class
var assembly = typeof(TSource).GetTypeInfo().Assembly;
var resourceName = assembly.GetManifestResourceNames().First(s => s.EndsWith(embeddedFileName,StringComparison.CurrentCultureIgnoreCase));
using (var stream = assembly.GetManifestResourceStream(resourceName))
if (stream == null)
throw new InvalidOperationException("Could not load manifest resource stream.");
using (var reader = new StreamReader(stream))
return reader.ReadToEnd();
【讨论】:
这是唯一对我有用的。非常感谢!【参考方案5】:我尚未在文档中确认这一点,但对我来说,检索 Resource.Designer.cs 中的嵌入文件的自动生成的资源代码现在似乎在 .NET Core 3.1 中再次运行。我现在可以通过调用返回 Bitmap 对象的 Properties.Resources.MyImageName 来检索嵌入的 jpg。
【讨论】:
streamreader 只检索字符。如果您的资源文件是基于字符的,则此方法有效 是的,现在可以了,但是您需要添加System.Resources.Extensions 包并在cs/vbproj 中添加<GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
。但与 .net 框架项目一起使用时可能会导致一些问题。见here以上是关于.Net Core 库中的嵌入式资源的主要内容,如果未能解决你的问题,请参考以下文章
使用 CMake 将资源(例如,着色器代码;图像)嵌入到可执行文件/库中
.NET Core嵌入式编程开关量GPIO(控制2个灯泡交替闪烁)
System.ServiceModel 错误在 ASP.NET Core API 中使用嵌入在 Windows 服务中的 WCF 时不支持操作