2011-04-26 4 views
17

저는 현재 주로 미국에서 사용되는 상당히 큰 ASP .NET Web Forms 응용 프로그램에서 작업합니다. 우리는 현재 세계의 다른 지역으로 옮겨 가고 있습니다. 물론 현재 우리는 응용 프로그램의 모든 영역을 현지화하기 위해 노력하고 있습니다. 일반적으로 우리의 접근 방식은 현재 스레드의 CurrentCulture 및 CurrentUICulture 속성을 각 요청의 시작 부분에 설정하여 현재 사용자의 로켈을 기반으로 적절한 형식 및 자원 추출을 지원하는 것입니다.일시적으로 현재 스레드의 culture를 변경하는 좋은 방법입니까?

그러나 현재 우리는 현재 사용자의 문화권 이외의 문화권을 사용하여 특정 비트의 코드를 실행해야하는 경우가 있습니다. 예를 들어 'User A'는 독일에 거주하지만 프랑스의 다른 회사와 비즈니스를하는 회사에서 근무합니다. '사용자 A'가 해당 프랑스 회사 중 하나에 대해 인보이스 (PDF)를 작성하려는 경우 해당 송장 생성 코드가 'de-DE'문화보다는 'fr-FR'문화로 실행되기를 바랍니다.

나는이 작업을 쉽게 수행 할 수있는 몇 가지 방법을 고려해 왔으며 올바르게 적용 할 것인지 궁금해하고 있습니다. 나의 주요 관심사는 성능과 스레드 안전성에 관한 것입니다.

하나의 접근법은 제공되는 문화권으로 주어진 작업을 실행하도록 설계된 정적 방법을 포함합니다. 이런 식으로 뭔가 :

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)); 

나는 또한 그것의 ctor의에서 스레드 문화를 설정하기위한 책임을 질 것으로 IDisposable을 구현하는 클래스를 만들 생각했습니다 그리고 Dispose 메서드로 원 문화를 되 돌리는 것이므로 다음과 같이 호출 할 수 있습니다.

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

나는이 모든 것을 잘못 알고 있습니까? 어느 접근법이 바람직할까요?

+2

나는 '사용하는'접근법을 좋아합니다. –

+0

사용 방법이 나에게 가장 좋은 방법이기도합니다. –

답변

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

2

여기에 대표적인 RunWithCulture 접근 방식에 투표하십시오.

위키 포스트에 대한 이유나 링크를 자유롭게 추가하십시오.

2

현재 스레드 문화를 일시적으로 변경하는 것이 좋은지 묻는 질문이므로 아니요 만 대답 할 수 있습니다. 일을 시작하기위한 다른 방법이없는 경우에만 사용할 수 있습니다. 이러한 전환은 오류가 발생하기 쉽기 때문입니다. OK, 조르단 (존경)이 준 코드로 다시 바꾸는 것을 잊지 않을 것이지만 ...
지금은 프랑스 청구서를 만들고 싶은 고객이 있습니다. 나는 당신이 프랑스 날짜, 숫자 및 통화 형식을 사용하기를 원한다고 가정합니다. 괜찮아. 하지만 ... 미래에 특정 미래가 다른 형식으로 인쇄 될 필요가 있다면 어떨까요? 못생긴 work-around를 만들 예정입니까?

나는 (소프트웨어를보고 같은 3 번째 자 독립형 솔루션이 될 수 있으며,이 ToString()을 처리하는 방법을 제어 할 수있다)가 당신의 통제 할 수 있다고 이해하지만 컨트롤 내에있는 경우, 내가 추천 처음부터 올바른 형식으로 데이터를 제공합니다. 예를 들어 일부 데이터 변환 레이어 (DTO)를 만들고 데이터 형식을 올바르게 지정할 수 있습니다 (ToString(IFormatProvider) 통해). 이것이 상당한 노력이라는 것을 알고 있지만, 올바른 방법을 요구하고 있기 때문에 ...

우리가 같은 조직에 있었고 I18n 코드 검토를한다면, 나는 일시적인 것이라고 지적 할 수 있습니다. 문화를 결함으로 변화시킨다. 일반적으로이를 피할 수있는 방법이 있습니다.

+0

응답 해 주셔서 감사합니다. "... 전환이 오류가 발생하기 쉽습니다"라고 말하면 유지 보수가 어려운 코드로 이어 지거나이 접근법으로 인해 응용 프로그램의 실제 런타임 오류가 발생할 수 있습니다. –

+0

은 또한, 나는이 있으며, toString를 사용하는 선택하지 않은 이유 중 하나는 (IFormatProvider를) 접근 방식은 그냥 올바른 날짜와 숫자 형식보다 더 필요하다; 또한 resx 파일에서 올바른 언어로 된 일부 정적 텍스트를 가져와야합니다. 현재 스레드에서 CurretUICulture 속성을 변경하지 않으면 서 현재 언어로 메시지를 가져 오는 효과적이고 안전한 방법을 아직 찾지 못했습니다. –

+0

오류가 발생하기 쉽기 때문에 유지 관리를 의미했습니다. 응용 프로그램의 다른 부분에서 오류가 발생해서는 안됩니다. 적어도 다시 되돌릴 것을 기억해야합니다. –

관련 문제