MRM 中的文件资源

MRM 中的文件资源实质上与字符串资源相同,不同之处在于,在运行时, ResourceCandidate.Kind 属性 将是 Path 而不是 String。 资源值只是字符串(文件名),而不是实际文件内容。 事实上,在大多数情况下,正在编制索引的文件甚至不需要在生成时存在。

如果目标应用程序将使用内置的 MRT 运行时 (Windows.ApplicationModel.Resources),则可以使用 ResourceCandidate.GetValueAsFileAsyncResourceCandidate.GetValueAsStreamAsync 自动查找和加载文件。 如果使用 MRT (Microsoft.Windows.ApplicationModel.Resources) 的 WinApp SDK 版本,则必须自行手动加载该文件。 还可以选择使用内置的 MRT 运行时手动加载文件。

可通过两种方法将文件添加到 MRM 索引器:

请注意,MrmIndexResourceContainerAutoQualifiers 不会将文件资源添加到索引器;而是在生成时加载命名文件,并将嵌入的资源直接复制到索引器。

有关按名称引用文件的替代项,可以使用 MrmIndexEmbeddedData 直接在 PRI 文件中嵌入数据 - 有关详细信息,请参阅下面的嵌入式数据

命名文件

基于文件的资源的主要原因是将字符串传递给 CreateFile()fopen()std::fstream 构造函数等函数。 由于文件的最终磁盘上路径通常在生成时未知,因此文件名通常是相对路径,将在运行时针对应用的工作目录(或其他一些已知目录)解析。 尽管可以包含任何任意字符串作为文件名(包括绝对路径或网络路径),但这通常并不有用。

项目根和相对文件名

通过 MrmCreateIndexer... 函数之一创建索引器时,必须指定 projectRoot 参数。 MrmIndexResourceContainerAutoQualifiers 使用此参数查找磁盘上要分析的文件,由 MrmIndexFileAutoQualifiers 从绝对路径计算相对路径。 MrmIndexFile 忽略了它。

嵌入式数据

将文件嵌入为数据可以减少应用所需的存储空间,并相对于引用文件名提高其性能。 不过,使用此功能有一些缺点,尤其是在内部循环应用开发期间。

在典型的 Windows 系统上,由于分配磁盘空间的方式,每个文件平均浪费 2kb 的磁盘空间。 对于包含大量小文件(如图标)的应用,此平均值可能更高。 通过将二进制文件数据直接嵌入 PRI 文件中,此每文件空间不会浪费。

此外,加载外部资源文件的速度比直接从 PRI 文件读取二进制数据慢,因为每个文件打开操作都需要额外的磁盘访问、安全检查等。 PRI 文件始终作为内存映射文件加载,因此访问数据速度更快。

尽管有这些好处,但使用嵌入式二进制数据有限制,尤其是在内部循环开发期间:

  • 生成时间增加,因为包含二进制数据的文件需要加载并添加到索引器。 添加基于文件的资源在生成时不需要额外的磁盘访问(磁盘访问会延迟到运行时)。
  • PRI 文件(通过 XML 转储)的调试问题更加困难,因为 XML 转储将包含 BASE64 编码的二进制数据,而不是人工可读的文件名。 此外,XML 转储文件将大大增加,从而使调试任何问题更加困难。
  • 由于文件的内容直接嵌入到 PRI 文件中,因此无法再实时交换资产。 任何嵌入资源的更改都需要完全重新生成 PRI 文件。 由于基于文件的资源仅包含文件名,因此可以随时更新实际资产文件。
  • 对于打包的应用,AppXManifest 中列出的图像资源(如“开始菜单”图标)无法嵌入,并且必须指定为文件资源。

出于这些原因,一般经验法则是在内部循环开发期间使用基于文件的资源,但考虑将嵌入式二进制资源用于最终生产版本(清单资源除外)。 对于打包的应用,请考虑将 AppXManifest 资源(如“开始菜单”图标)放置在与其他资源的单独直接位置中,以简化生成过程(AppXManifest 资源添加为文件,以及添加为嵌入数据的其他资源)。