【问题标题】:How to get all Cultures to avoid CultureNotFoundException如何让所有文化避免 CultureNotFoundException
【发布时间】:2013-04-12 09:30:14
【问题描述】:

伙计们,我正在开发一个可以跨多台机器运行的应用程序。我最近在其中引入了Cultures 以支持所有货币。

我有 2 台主要的开发 PC,我在它们之间移动代码。一台是 Windows 8 笔记本电脑,另一台是 Windows 7 PC。

这两台机器中SpecificCultures的列表好像一样。当可执行文件在 Windows 8 上运行时,会返回更多的 SpecificCultures,并且还会重命名一些现有的。

我使用以下代码转储所有特定文化的文本文件:

StringBuilder sb = new StringBuilder();

foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
{
    sb.Append(ci.Name + "\t" + new RegionInfo(ci.LCID).CurrencyEnglishName);
    sb.AppendLine();
}

StreamWriter f = new StreamWriter(@"specificCulturesFound.txt");
f.Write(sb);
f.Close();

从我的 Windows 8 笔记本电脑返回的 SpecificCultures 是:http://pastebin.com/cznLRG62 从我的 Windows 7 PC 返回的SpecificCultures 是这样的:http://pastebin.com/MwMXwSdb

如果您在 Notepad++ 或其他工具中比较它们,您会发现差异。

例如:例如,et-EE Estonian Kroon 条目仅适用于我的 Windows 7 PC,而 ku-Arab-IQ Iraqi Dinar 仅适用于 Windows 8 笔记本电脑

问题是,我该如何处理这种情况?应用程序发布后,将在具有不同 .NET 框架版本的不同机器上运行。

有没有办法通过应用程序导出所有收集的 CultureInfo 数据,以便可以使用它而不是从已安装的 .NET 框架中获取它?

【问题讨论】:

标签: c# c#-4.0 currency cultureinfo culture


【解决方案1】:

这不是一个简单的情况,在正常情况下您的应用程序不应该意识到文化之间的差异,它应该意识到存在差异。

这通常是将所有内容保存在中性文化中(例如,en-US 区域设置)然后转换回用户的特定区域设置应用程序运行。例如,如果用户输入日期值列表,您保存它们的方法是将每个日期转换为其中性表示并使用列表分隔符连接它们(两者都使用中性文化,您可以这样做,因为您可以获得当前用户的语言环境,您知道中立的语言环境)。稍后,在另一台具有不同语言环境的机器上,其他人将读取该文件,您的应用程序知道该日期是中性文化,然后它可以读取它们并将它们以所需的格式呈现给用户。示例:

  • 区域设置为it-IT 的用户输入两个日期:01/01/1960;25/12/2013
  • 应用程序以中性en-US 格式存储它:01/01/1977,12/25/2013
  • 具有jp-JP 区域设置的另一个用户将读取它,应用程序将读取中性区域设置并将其显示为1977/01/01・2013/12/25 给用户。

如果这些数据不固定,例如货币,事情就会变得更加复杂。在这种情况下,您不能简单地转换为中性值,让我们想象一下(值非常随机):

  • 用户输入一个值,例如 1000 日元。
  • 日元兑换成美元(假设 100 日元 = 1 美元):10 美元,然后您保存它。
  • 数据将在另一个使用欧元的欧洲国家/地区读取,应用程序读取 10 美元,然后将其转换为 10 欧元。

这是错误的当然是因为:

  • 更改日元 美元可能会从您写它的那一天到它以欧元读取的那一天发生变化。
  • 兑换日元 欧元不等于日元 美元 欧元。

这不是一个容易解决的问题,您根本不能依靠CultureInfo 的“自动”转换,但您必须自己实现(以最适合您要求的方式)。例如(当然非常幼稚)实现可能会像这样存储货币:

struct CurrencyValue
{
    public decimal Value;
    public string Currency;
}

这可能会根据需要变得复杂(例如,使用类层次结构而不是货币而不是字符串),但请记住,这种转换绝对不是微不足道的。

总结

不要关心这种转换,只需使用中性语言环境存储所有内容,并且转换(到和从)将在用户计算机中发生(您不需要关心正在使用哪个语言环境)。

如果您必须管理像货币这样的特殊类型,那么您必须实现自己的库来以正确的方式处理它们。什么是“正确的方式”取决于您的完整应用程序要求,因此无法在这里回答。

【讨论】:

  • 感谢您的回复!问题是我的应用程序中有很多与金钱相关的东西。一种特殊用途是用户需要指定价格。这是通过首先从下拉列表中选择货币(例如US Dollar),然后在文本框中指定数值来完成的。我实际上将用户选择的语言环境与数值一起存储在数据库中。现在假设用户选择了一种货币,该货币在一台机器上IS 可用,而在另一台机器上IS NOT 可用。在这种情况下,当应用程序在数据库中读取该货币的区域设置时,它不会知道它是哪种货币。
  • 名称可能不同,您不应依赖它们,LCID 更稳定,因此您应该存储/使用它们(但较新的版本可以支持旧版本中不存在的语言环境) .要获取所有文化,您应该使用 CultureTypes.AllCultures 并获取 CultureInfo,您可以使用 CultureInfo.GetCultureInfo() 和您需要的 LCID。当然,必须处理 LCID 未知的情况(但使用不太可能的 ID)。
  • 是的,我想 LCID 会比 ku-Arab-IQ 更安全。但我仍将如何处理未知的 LCID 案例?我认为使用 LCID 代替 ku-Arab-IQ 之类的东西不会真正帮助我解决这个问题。还是我错过了什么?
  • 嗯,名称可能会改变(例如,因为一个国家的政治定义发生了变化),但它的 LCID 将保持不变)。此外,有时将相同的名称分配给不同的语言环境,因为它是同一个国家(例如印度)。无论如何,是的,您必须处理 ID 不存在的情况(这可能不太可能,但至少是可能的)。如何?您可以在您的应用程序中部署一个包含基本所需信息的已知文化列表,当您有一个未知 ID 时,您可以创建一个自定义 CultureInfo 并用该信息填充它。
  • 这不会将您的用户限制在该列表中,它会让您有机会处理 Windows 版本之间的此类更改(至少作为 在提示错误之前的最终回退)。
猜你喜欢
  • 2011-08-22
  • 1970-01-01
  • 2012-12-25
  • 1970-01-01
  • 1970-01-01
  • 2018-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多