我在一个相当大的ASP .NET Web Forms应用程序上工作,该应用程序目前主要在美国使用。我们正在将其推广到世界其他地区,这当然意味着我们正在努力本地化应用程序的所有领域。一般来说,我们的方法是在每个请求开始时设置当前线程的CurrentCulture和CurrentUICulture属性,以支持基于当前用户的语言环境进行正确的格式化和资源提取。
但是,在某些情况下,我们需要使用除当前用户文化之外的文化来运行某些代码。例如,“用户A”居住在德国,但适用于与法国其他公司有业务往来的公司。当“用户A”想要为其中一家法国公司创建发票(PDF)时,我们希望发票生成代码以“fr-FR”文化而非“de-DE”文化运行。
我已经考虑过几种方法可以很容易地做到这一点,我想知道我是否正确地做到了这一点。我主要关心的是性能和线程安全性。
一种方法涉及一种静态方法,旨在使用提供的文化运行给定任务。像这样:
public static void RunWithCulture(CultureInfo culture, Action task)
{
if (culture == null)
throw new ArgumentNullException("culture");
var originalCulture = new
{
Culture = Thread.CurrentThread.CurrentCulture,
UICulture = Thread.CurrentThread.CurrentUICulture
};
try
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
task();
}
finally
{
Thread.CurrentThread.CurrentCulture = originalCulture.Culture;
Thread.CurrentThread.CurrentUICulture = originalCulture.UICulture;
}
}
然后可以像这样调用此方法:
var customerCulture = new CultureInfo(currentCustomer.Locale);
CultureRunner.RunWithCulture(customerCulture, () => invoiceService.CreateInvoice(currentCustomer.CustomerId));
我还考虑创建一个实现IDisposable的类,它负责在它的ctor中设置线程文化,然后在Dispose方法中返回原始文化,所以你可以像这样调用它:
var customerCulture = new CultureInfo(currentCustomer.Locale);
using(new CultureRunner(currentCustomer.Locale))
{
invoiceService.CreateInvoice(currentCustomer.CustomerId);
}
我是否认为这一切都错了?哪个,如果这些方法中的任何一个更可取?
答案 0 :(得分:15)
我喜欢using
方法。我还创建了一个扩展方法,以便更好地阅读:
var customerCulture = new CultureInfo(currentCustomer.Locale);
using (customerCulture.AsCurrent()) {
invoiceService.CreateInvoice(currentCustomer.CustomerId);
}
这样的事情:
public static class CultureInfoExtensions {
public static IDisposable AsCurrent(this CultureInfo culture) {
return new CultureRunner(culture);
}
}
或者,如果始终是您的客户对象设置文化,另一种扩展方法将进一步提升抽象:
using (currentCustomer.CultureContext()) {
invoiceService.CreateInvoice(currentCustomer.CustomerId);
}
答案 1 :(得分:2)
既然你在问临时改变当前线程的文化是否好主意,我只能回答:没有。只有在没有其他办法让事情发挥作用的情况下才可以使用它。这只是因为这种切换容易出错。好的,你不会忘记用Jordão(尊重)给你的代码改回来,但是......
目前,您的客户想要创建法国发票。我假设你想使用法国日期,数字和货币格式。没关系。但是......如果将来某些未来需要以其他格式打印出来,例如这种原始德语,会怎么样?你打算创造一些丑陋的工作吗?
我知道它可能超出您的控制范围(如报告软件可能是3 rd 派对独立解决方案,您无法控制它如何处理ToString()
)但如果它在你的控制范围内,我建议首先以正确的格式提供数据。例如,您可以正确创建一些数据转换层(DTO)和格式数据(通过ToString(IFormatProvider)
)。我知道这是一项非常努力,但是因为你在询问正确的做事方式......
如果我们在同一个组织中并且我会进行I18n代码审查,那么您可以确定我会指出暂时改变文化作为缺陷。通常有一种方法可以避免这种情况。