这是暂时改变当前线程文化的好方法吗?

我在一个相当大的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); } 

我错了吗? 哪个,如果这些方法中的任何一个更可取?

我喜欢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); } 

在这里投票给代表RunWithCulture方法。

随意添加这个维基帖的原因/链接。

既然你在问临时改变当前线程的文化是不是一个好主意,我只能回答: 。 只有在没有其他办法让事情发挥作用的情况下才可以使用它。 这只是因为这种切换容易出错。 好的,你不会忘记用Jordão(尊重)给你的代码改回来,但……
目前,您的客户想要创建法国发票。 我假设你想使用法国日期,数字和货币格式。 没关系。 但是……如果将来某些未来需要以其他格式打印出来,例如这个原始的德国人呢? 你打算创造一些丑陋的工作吗?

我知道它可能超出你的控制范围(就像报告软件可能是第三方独立解决方案而你无法控制它如何处理ToString() )但是如果它在你的控制范围内,我会建议输入数据正确的格式首先。 例如,您可以正确创建一些数据转换层(DTO)和格式数据(通过ToString(IFormatProvider) )。 我知道这是一个很大的努力但是因为你问的是正确的做事方式……

如果我们在同一个组织中并且我会进行I18n代码审查,那么您可以确定我会指出暂时改变文化作为缺陷。 通常有一种方法可以避免这种情况。