2011-04-26 19 views
17

我工作在一個相當大的ASP .NET Web窗體應用程序,目前主要在美國使用。我們正在將其推廣到世界其他地區,這當然意味着我們正在努力將應用程序的所有領域本地化。一般來說,我們的方法是在每個請求的開始處設置當前線程的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這將是負責設置線程的文化,在它的構造函數然後將原始文化返回到Dispose方法中,因此您可以這樣稱呼它:

var customerCulture = new CultureInfo(currentCustomer.Locale); 
using(new CultureRunner(currentCustomer.Locale)) 
{ 
    invoiceService.CreateInvoice(currentCustomer.CustomerId); 
} 

我是否在談論全部錯誤?哪一種方法更好?

+2

我喜歡'使用'的方法。 – 2011-04-26 16:06:52

+0

使用方法對我來說也是最好的。 – 2011-04-26 16:08:32

回答

13

我喜歡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); 
} 
+0

您可以添加更通用的示例,因爲CultureRunner未聲明。我需要運用不同文化的方法。你能更新你的答案嗎? – Pedro77 2014-08-21 15:09:07

2

爲委託RunWithCulture方法投票在這裏。

隨意添加此wiki文章的原因/鏈接。

2

既然你問是否暫時改變當前主題的文化是好主意,我只能回答:沒有。如果並且只有沒有其他方式才能使事情順利進行,可以使用它。那只是因爲這種切換很容易出錯。好的,你不會忘記用代碼Jordão(尊重)給你的東西換回東西,但是...
現在你有客戶想要創建法國發票。我假設你想使用法語日期,數字和貨幣格式。沒關係。但是......如果將來某個未來需要用其他格式打印出來,比如說這個原始的德語呢?你會創造一些醜陋的工作?

我明白,這可能是你無法控制的(如報告軟件可能是3 黨獨立解決方案,你無法控制它是如何處理ToString()),但如果它是你的控制範圍之內,我會建議首先以正確的格式提供數據。例如,您可以創建一些數據轉換層(DTO)並正確格式化數據(通過ToString(IFormatProvider))。我知道這是一個相當努力,但因爲你問的是正確的方式來做事情...

如果我們在同一個組織,我會做I18n代碼審查,你可以肯定我會指出臨時改變文化作爲缺陷。通常有一種方法可以避免這種情況。

+0

感謝您的回覆。當你說「......這種切換很容易出錯」,你的意思是說它可能導致難以維護的代碼,或者這種方法會導致應用程序中的實際運行時錯誤? – 2011-04-27 12:25:37

+0

另外,我沒有選擇使用ToString(IFormatProvider)方法的原因之一是我需要的不僅僅是正確的日期和數字格式;我還需要從resx文件中以正確的語言提取一些靜態文本。我還沒有找到一種有效和安全的方法來使用當前語言來引入消息,而不會改變當前線程中的CurretUICulture屬性。 – 2011-04-27 12:27:02

+0

由於容易出錯,我的意思是維護。它不應該在應用程序的其他部分導致錯誤,至少在您記得將其切換回來時。 – 2011-04-27 14:21:31

相關問題