导读:本期聚焦于小伙伴创作的《C# EmbeddedFileProvider如何读取嵌入资源?内嵌文件提供程序使用详解》,敬请观看详情。把配置文件或静态资源打包进程序集后,怎么在运行时像访问普通文件一样读取它们?EmbeddedFileProvider基于程序集清单资源工作,通过GetManifestResourceNames拿到内嵌资源名,再由IFileInfo抽象出流。相比手动Assembly.GetManifestResourceStream,它统一了文件提供程序接口,可直接接入Mvc静态文件或本地化系统。实际使用时要注意资源命名规则受项目默认命名空间与文件夹结构影响,容易出现找不到资源的误区。本文从原理到代码演示如何构建provider并遍历读取内嵌文件内容。

在C#项目中,将文本、图片或配置文件作为嵌入资源编译进程序集,可以有效避免部署时文件丢失的问题。EmbeddedFileProvider是Microsoft.Extensions.FileProviders命名空间下提供的专用类型,它把程序集里的内嵌资源包装成统一的IFileProvider接口,使我们可以用一致的方式读取内容。

C# EmbeddedFileProvider如何读取嵌入资源?内嵌文件提供程序使用详解

一、嵌入资源与程序集命名规则

在Visual Studio中,把一个文件设为“嵌入的资源”生成操作,编译器会将其写入程序集清单。资源名并不是原始文件名,而是由项目的默认命名空间、文件夹路径和文件名共同拼接而成。例如默认命名空间为MyApp,文件位于Resources目录下名为config.json,那么最终资源名通常是MyApp.Resources.config.json。

这种命名方式经常让初学者在调用GetManifestResourceStream时传入错误名称而返回null。我们可以通过反射列出所有资源名来排查。理解这一规则是使用EmbeddedFileProvider的前提,因为provider内部也是依据这些名称来定位资源的。

using System;
using System.Reflection;

var asm = Assembly.GetExecutingAssembly();
foreach (var name in asm.GetManifestResourceNames())
{
    Console.WriteLine(name);
}

二、EmbeddedFileProvider基本用法

EmbeddedFileProvider的构造函数接收Assembly,并可指定基础命名空间。创建后,通过GetFileInfo方法传入相对于基础命名空间的资源路径,即可获得IFileInfo对象。IFileInfo的Exists属性指示资源是否存在,OpenReadStream方法返回只读流,这与物理文件提供程序的行为完全一致。

下面示例展示如何读取内嵌的config.json。假设基础命名空间已设为MyApp,资源放在Resources文件夹,则路径写为Resources/config.json。注意路径使用正斜杠,provider会自动映射到对应的清单资源名。

using Microsoft.Extensions.FileProviders;
using System;
using System.IO;
using System.Reflection;

var assembly = Assembly.GetExecutingAssembly();
// 指定基础命名空间,后续路径可省略该前缀
var provider = new EmbeddedFileProvider(assembly, "MyApp");

IFileInfo file = provider.GetFileInfo("Resources/config.json");
if (file.Exists)
{
    using var stream = file.OpenReadStream();
    using var reader = new StreamReader(stream);
    string content = reader.ReadToEnd();
    Console.WriteLine(content);
}
else
{
    Console.WriteLine("未找到嵌入资源");
}

三、遍历与目录检索

除了单个文件,EmbeddedFileProvider也支持GetDirectoryContents方法。它返回一个IDirectoryContents,包含该“目录”下的所有资源条目。由于嵌入资源本质是扁平的清单名称,provider会根据基础命名空间和路径前缀模拟出目录结构,方便与需要目录枚举的组件集成。

以下代码列出Resources目录下的所有内嵌资源。若某个子项IsDirectory为false,即可作为文件读取。这种能力在构建可插拔模块、提供多语言资源包时非常实用,无需关心物理路径。

using Microsoft.Extensions.FileProviders;
using System;
using System.Reflection;

var provider = new EmbeddedFileProvider(Assembly.GetExecutingAssembly(), "MyApp");
var dir = provider.GetDirectoryContents("Resources");
foreach (var item in dir)
{
    Console.WriteLine($"名称: {item.Name}, 是否目录: {item.IsDirectory}");
}

四、在依赖注入与框架中的集成

ASP.NET Core等框架大量使用IFileProvider。我们可以把EmbeddedFileProvider注册到服务容器,或合并到CompositeFileProvider中,同时支持物理文件和嵌入资源。例如在静态文件中间件或Razor视图定位器中,嵌入资源能作为备用来源,提升发布包的自包含性。

下面演示如何用ServiceCollection添加嵌入文件提供程序,并在开发中组合多个来源。这种方式让业务代码只依赖IFileProvider抽象,不感知资源究竟来自磁盘还是程序集,降低了部署复杂度。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using System.Reflection;

var services = new ServiceCollection();
var embedded = new EmbeddedFileProvider(Assembly.GetExecutingAssembly(), "MyApp");
services.AddSingleton<IFileProvider>(embedded);

var provider = services.BuildServiceProvider().GetRequiredService<IFileProvider>();
var info = provider.GetFileInfo("Resources/config.json");
Console.WriteLine(info.Exists);

五、常见误区与排查建议

最常见的错误是资源名不匹配。若GetFileInfo总是返回Exists为false,应先打印GetManifestResourceNames确认实际名称。另一个误区是混淆默认命名空间与程序集名称,基础命名空间参数应为代码中的默认命名空间,而非Assembly.GetName().Name。

此外,嵌入资源在编译后无法修改,适合只读场景。若需要运行时改写,应改用物理文件或外部配置中心。理解这些边界,才能在高内聚发布与灵活配置之间做出合理选择。

EmbeddedFileProvider嵌入资源Assembly修改时间:2026-08-05 22:45:30

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。