Как установить DateTimeFormatInfo.CurrentInfo и NumberFormatInfo.CurrentInfo в инвариант? - PullRequest
1 голос
/ 27 марта 2019

Я выполняю рефакторинг некоторых модульных тестов и обнаружил, что некоторые стратегии синтаксического анализа основаны на 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 Ответ

3 голосов
/ 27 марта 2019

Если я вас правильно понимаю, вы хотите запустить какой-то код (тесты) в соответствии с культурой, равной 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 && 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
  }
...