Can DataSet.ReadXml be fully culture invariant?

2019-08-07 16:05发布

I am attempting to convert a DataSet to XML and then read it back in a culture-invariant manner. At first this seemed easy, since DataSets use the invariant culture by default.

For my first test, I switched to the French locale and verified that the DataSet's WriteXml method used invariant culture settings for doubles. So far, so good.

For the second test, I used the Customize Format dialog under Region and Languages to change the decimal symbol to '#' and and negative sign symbol to '~'. To my surprise, this broke my unit test. The XML was still being written using invariant settings, but when I attempted to read the same XML back, I got a System.Format exception saying the input string was in an incorrect format. According to the stack trace, the ReadXml method was attempting to parse the value as an Int32, even though I explicitly set the type of the column to Double! Changing the decimal symbol and negative sign symbol back to the French defaults fixed the issue.

My test code is shown below.

[TestMethod]
public void TestDataSetSerialization()
{
    // Verify that the locale settings are being picked up.
    double testValue = -3.1;
    string expectedInvariantText = "-3.1";
    string expectedLocaleText = "~3#1";
    string actualLocaleText = testValue.ToString();
    Assert.AreEqual(expectedLocaleText, actualLocaleText);

    double actualLocaleValue = Double.Parse(expectedLocaleText);
    Assert.AreEqual(testValue, actualLocaleValue);
    double actualInvariantValue = Double.Parse(expectedInvariantText, System.Globalization.CultureInfo.InvariantCulture);
    Assert.AreEqual(testValue, actualInvariantValue);

    // Check the data set's WriteXml and ReadXml methods.
    DataSet dataSet = new DataSet();
    dataSet.Locale = System.Globalization.CultureInfo.InvariantCulture;
    DataTable dataTable = new DataTable();

    const string columnName = "Double Values";
    DataColumn dc = new DataColumn(columnName, typeof(double));
    dataTable.Columns.Add(dc);

    double[] doubleList = new double[] { 0.0, -1.1, 1.2 };
    foreach (object doubleValue in doubleList)
    {
        DataRow dataRow = dataTable.NewRow();
        dataRow[columnName] = doubleValue;
        dataTable.Rows.Add(dataRow);
    }

    dataSet.Tables.Add(dataTable);
    StringBuilder dataSetXml = new StringBuilder();
    using (XmlWriter writer = XmlWriter.Create(dataSetXml))
    {
        dataSet.WriteXml(writer, XmlWriteMode.WriteSchema);
    }

    StringReader reader = new StringReader(dataSetXml.ToString());
    DataSet readDataSet = new DataSet();
    readDataSet.Locale = System.Globalization.CultureInfo.InvariantCulture;

    // This throws a number format exception on a call to ParseInt32.
    readDataSet.ReadXml(reader, XmlReadMode.ReadSchema);
}

0条回答
登录 后发表回答