Как установить DateTimeFormatInfo.CurrentInfo и NumberFormatInfo.CurrentInfo в инвариантные?

#c# #.net #.net-core #cultureinfo

#c# #.net #.net-ядро #cultureinfo

Вопрос:

Я рефакторингую некоторые модульные тесты и обнаружил, что некоторые стратегии синтаксического анализа основаны на DateTime.TryParseExact и sbyte.TryPase , которые сами зависят от NumberFormatInfo.CurrentInfo и DateTimeFormatInfo.CurrentInfo .

Чтобы правильно организовать мои модульные тесты, я решил настроить CurrentInfo свойство обоих NumberFormatInfo и DateTimeFormatInfo на их инвариантные варианты через:

 CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
  

Однако из любопытства я попытался проверить, были ли соответствующие InvariantInfo настроены с помощью модульного теста, и оказалось, что нет, это не так. Мне интересно, чего мне здесь не хватает, чтобы InvariantCulture применить эти два CurrentInfo

 [Fact]
public void ShouldReturnInvariantInfo()
{
    CultureInfo.CurrentCulture.NumberFormat = NumberFormatInfo.InvariantInfo;
    CultureInfo.CurrentCulture.DateTimeFormat = DateTimeFormatInfo.InvariantInfo;
    NumberFormatInfo.CurrentInfo.Should().Be(NumberFormatInfo.InvariantInfo);
    DateTimeFormatInfo.CurrentInfo.Should().Be(DateTimeFormatInfo.InvariantInfo);
}
  

Зная, что базовые реализации:

NumberFormatInfo.InvariantInfo :

 public static NumberFormatInfo CurrentInfo
{
  get
  {
    CultureInfo currentCulture = CultureInfo.CurrentCulture;
    if (!currentCulture._isInherited)
    {
      NumberFormatInfo numInfo = currentCulture.numInfo;
      if (numInfo != null)
        return numInfo;
    }
    return (NumberFormatInfo) currentCulture.GetFormat(typeof (NumberFormatInfo));
  }
}
  

DateTimeFormatInfo.CurrentInfo :

 public static DateTimeFormatInfo CurrentInfo
{
  get
  {
    CultureInfo currentCulture = CultureInfo.CurrentCulture;
    if (!currentCulture._isInherited)
    {
      DateTimeFormatInfo dateTimeInfo = currentCulture.dateTimeInfo;
      if (dateTimeInfo != null)
        return dateTimeInfo;
    }
    return (DateTimeFormatInfo) currentCulture.GetFormat(typeof (DateTimeFormatInfo));
  }
}
  

Ответ №1:

Если я вас правильно понимаю, вы хотите запустить некоторый код (тесты) в культуре, которая является Current одной, за исключением NumberFormat и DateTimeFormat которые Invariant . Если это ваш случай, я предлагаю использовать Clone текущий язык и изменить клон:

 // Current culture clone
CultureInfo testCulture = CultureInfo.CurrentCulture.Clone() as CultureInfo;

// modified: current culture except Number and DateTime which are Invariant
testCulture.NumberFormat = CultureInfo.InvariantCulture.NumberFormat;
testCulture.DateTimeFormat = CultureInfo.InvariantCulture.DateTimeFormat;

// and, finally, set back as current
CultureInfo.CurrentCulture = testCulture;
  

Давайте посмотрим на форматы

 Console.Write(ReferenceEquals(CultureInfo.CurrentCulture.DateTimeFormat,
                              CultureInfo.InvariantCulture.DateTimeFormat) 
     ? "Equals" 
     : "Not Equals");
  

Результат:

 Equals
  

Редактировать: Чтобы запускать код using с измененной культурой, мы можем реализовать для него класс:

   public class TestCulture : IDisposable {
    private CultureInfo m_SavedCulture; 
    private CultureInfo m_TestCulture;
    private bool m_IsDisposed;

    public TestCulture() {
      m_SavedCulture = CultureInfo.CurrentCulture; 

      m_TestCulture = CultureInfo.CurrentCulture.Clone() as CultureInfo;
      m_TestCulture.NumberFormat = CultureInfo.InvariantCulture.NumberFormat;
      m_TestCulture.DateTimeFormat = CultureInfo.InvariantCulture.DateTimeFormat;

      CultureInfo.CurrentCulture = m_TestCulture;
    }

    protected vitrual void Dispose(bool disposing) {
      if (disposing) {
        if (!m_IsDisposed amp;amp; ReferenceEquals(CultureInfo.CurrentCulture, m_TestCulture)) {
          CultureInfo.CurrentCulture = m_SavedCulture;

          m_IsDisposed = true;
        }
      }
    }

    public void Dispose() => Dispose(true);
  }
  

А затем использовать их следующим образом:

   using (new TestCulture()) {
    // Tests which should be run under the specific culture
  }