【问题标题】:Can we skip ResourceManager?我们可以跳过 ResourceManager 吗?
【发布时间】:2014-06-29 02:44:53
【问题描述】:

我正在从事一个广泛使用 ResourceManager 的项目,而这个问题刚刚闪过我的脑海。 我们可以在不使用 ResourceManager 的情况下读取 .resx 文件吗?我的意思是,还有其他方法吗?

【问题讨论】:

  • 你为什么对这个感兴趣?
  • .resx 文件只是 XML 文件...和任何其他 XML 文件一样,您可以轻松读取和解析这些 .resx 文件,如果您觉得需要这样做...。 .
  • @marc_s: 是的,.resx 只是 XML 文件,但它们的内容将被转换为集成在 .exe.dll 文件中的代码;即.resx 文件仅在编译时访问,而不是在运行时访问。

标签: c#


【解决方案1】:

ResourceManager 是一个便利类,它与构建系统支持.resx 文件的方式配合得很好。不,这不是绝对必要的。

.NET 程序集具有将任意数据嵌入程序集清单的通用能力。只是一个字节,它可以是你想要的任何东西。构建系统也直接支持,只需将文件添加到您的项目并将其构建操作设置为“嵌入式资源”。在运行时,您使用Assembly.GetManifestResourceStream() 检索该文件中的数据。

您可以在此处停下来,但这只是一个文件,如果您有许多要嵌入的小资源,它的扩展性就不是很好。这是 .resx 文件开始的地方,它是一个 XML 文件,其中包含友好格式的资源。当原件丢失时,它可以让您有机会再次找回源头。

但是 XML 格式对于资源数据来说并不是一个很好的格式,它体积庞大,而且找回数据的成本很高。所以 .NET 有 resgen.exe,这是一个构建工具,可以将 XML 文件转换为二进制文件,即 .resources 文件。紧凑且易于找回的东西。并且适合作为单个清单资源直接嵌入。

不想要做的是必须自己读取 .resources 数据。您需要使用一个帮助类,该类可以从字节块中找到特定资源。你想使用ResourceReader class,它的GetResourceData()让你指定资源名称,它会吐出资源类型和数据。

您可以在此停下来,但一个应用程序通常需要不同的资源集。一个非常常见的本地化需求。这就是卫星组件的全部意义所在,不同的组件只包含资源,每个组件都针对特定的文化。它们是分开的,因此当您只需要一组本地化资源时,您无需为存储所有本地化资源所需的虚拟内存付费。这里需要一个帮助类,它可以根据当前的文化自动定位和加载正确的附属程序集并为您检索资源。

那个助手类是ResourceManager

【讨论】:

  • 很好的回应!我还没有冒险使用resgen。我一直在做一些简单的本地化工作,严格围绕字符串资源,但我可以看到如果我的需求扩展到包括其他资源类型,这将如何成为下一步。
  • @Hans 确实是一个非常彻底的回应。我在二进制“包装”方面学到了一些东西。谢谢。
【解决方案2】:

如果您选择跳过使用 ResourceManager,您可以让 Visual Studio 为您处理代码生成。最终生成的代码使用ResourceManager,但您不再手动编写该代码。此外,由于您引用的是生成的静态类,因此您会获得编译时检查。

如果您将资源文件添加到项目并从解决方案资源管理器中双击它,Visual Studio 会显示一个对话框,您可以在其中输入资源的名称及其值。该对话框为您提供了将资源添加为字符串、图像、音频等的选项(查看对话框顶部的下拉菜单)。接下来,要获取代码生成位,您需要将Access Modifier 设置为“公共”或“内部”。第三个选项是“不生成代码”。

例如,添加一个名为“MyResources”的资源文件,然后添加一个字符串资源,其名称GreetingHello!,其中之一选择用于代码生成的前两个选项(从 public 开始测试它,根据需要限制访问),您现在应该能够通过 MyResources.Greeting 从代码中引用资源。如果您没有立即看到它,请确保您已保存文件并尝试编译。

string greeting = MyResources.Greeting; // "Hello!"

如果您添加其他资源类型(图像、音频等),那么返回类型当然会有所不同。

此时您可以检查生成的.cs 文件并查看生成的代码使用ResourceManager。资源文件的另一个用途是本地化。假设您想要一个西班牙语版本的MyResources。您将添加一个名为MyResources.es.resx 的新文件,其中es 对应于所需的语言代码(在本例中为西班牙语)。现在添加相同的资源名称Greeting,西班牙语值为Hola!

如果您将线程文化更改为西班牙语,现在引用资源将返回西班牙语版本:

string defaultGreeting = MyResources.Greeting; // "Hello!"
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("es");
string spanishGreeting = MyResources.Greeting; // "Hola!"

请注意,您只需将访问修饰符设置为默认资源文件(即MyResources.resx)的代码生成选项之一,而不是您添加的所有其他本地化版本。这样做没有坏处,但在我看来,生成主文件而其他文件只具有所需的资源值而不生成代码会更干净。

【讨论】:

  • 请参阅this answer,了解如何将资源文件放在Properties 文件夹中,然后通过YourProject.Properties 命名空间访问它们。 (请注意,通过 Properties => Resources,Visual Studio 将允许您通过类 YourProject.Properties.Resources 访问 single resource file。)
【解决方案3】:

嗯,资源被编译到程序集中。您可以尝试通过读取字节(或 IL)来读取程序集,并从中提取资源。

ResourceManager 为您完成了这一切,所以我想不出您想要这样做的任何原因...也许一个,如果您不想将程序集加载到内存中,您可以在没有 ResourceManager 的情况下执行此操作。

【讨论】:

    【解决方案4】:

    参考 Microsoft:表示资源管理器,可在运行时方便地访问特定于文化的资源。

    我希望,我希望你使用 multi Lang,你会得到更一致的结果和更好的兼容性。

    恕我直言

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-11
      • 2021-03-15
      • 1970-01-01
      • 2021-03-30
      • 1970-01-01
      • 1970-01-01
      • 2013-02-04
      相关资源
      最近更新 更多