#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
}