如何设置DateTimeFormatInfo.CurrentInfo和NumberFormatInfo.CurrentInfo不变?

How to set DateTimeFormatInfo.CurrentInfo and NumberFormatInfo.CurrentInfo to invariant?

我正在重构一些单元测试,发现一些解析策略依赖于 DateTime.TryParseExactsbyte.TryPase,它们本身依赖于 NumberFormatInfo.CurrentInfoDateTimeFormatInfo.CurrentInfo.

为了正确安排我的单元测试,我决定通过以下方式将 NumberFormatInfoDateTimeFormatInfoCurrentInfo 属性 设置为它们不变的风格:

CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;

然而,出于好奇,我试图检查相应的 InvariantInfo 是否通过单元测试设置,结果证明没有,它们不是。我想知道在这两个 CurrentInfo

中强制执行 InvariantCulture 我在这里缺少什么
[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));
  }
}

如果我对你的理解是正确的,你想要 运行 一些代码(测试)在 Current 文化下,除了 NumberFormatDateTimeFormatInvariant。如果是你的情况,我建议 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修改后的文化,我们可以实现一个class 为它:

  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
  }