在C#中,通常将基元转换为字符串以进行序列化的安全方法是什么?

时间:2014-12-02 01:24:24

标签: c# string serialization deserialization

我想在C#中一般地序列化一个类/结构。为简单起见,我们假设类/结构只能是一层深(没有结构的结构)。

这是我想写的内容

System.Text.StringBuilder builder = new System.Text.StringBuilder();

System.Reflection.FieldInfo[] fields = obj.GetType().GetFields();
foreach (System.Reflection.FieldInfo info in fields) {
    object fieldValue = info.GetValue(obj);
    if (fieldValue != null) {
        builder.Append(fieldValue.ToString());
    }
    ...
}

不幸的是,据我所知,这是行不通的,因为ToString()对文化非常敏感。换句话说,对于Single,它可能会输出12.34512,345,具体取决于文化设置。

是否还有一些其他非文化敏感的ToString我可以调用原始类型?

此外,对象函数是否存在非文化敏感的通用字符串。我正在使用

object value = System.Convert.ChangeType(string, someType);

但这显然也是文化敏感的。 :(

4 个答案:

答案 0 :(得分:4)

对于ChangeType,有overload which accepts an IFormatProvider,因此您可以致电:

System.Convert.ChangeType(string, someType, CultureInfo.InvariantCulture);

答案 1 :(得分:2)

  

是否有一些其他非文化敏感的ToString我可以调用原始类型?   此外,对象函数是否存在非文化敏感的通用字符串

恕我直言,最简单的解决方案是格式化字符串并传递格式化程序。这样您就不必单独显式处理每个单独的值。

例如:

foreach (System.Reflection.FieldInfo info in fields) {
    object fieldValue = info.GetValue(obj);
    builder.AppendFormat(CultureInfo.InvariantCulture, "{0}", fieldValue);
    ...
}

这适用于覆盖ToString()的任何对象,但当然并非所有对象都必须实现IFormattable。对于那些人,无论他们的正常ToString()覆盖是什么,都将使用(可能仍然依赖于文化)。 C#原语将以这种方式工作。

注意:正如Stuart所指出的,复合格式化系统将自动处理null值(返回空字符串),因此如果使用上述内容,您甚至不需要检查。

换句话说,上面的内容与检查IFormattable基本相同,如果支持则使用它,否则返回ToString()。编写的代码更少。 :)

答案 2 :(得分:0)

如果您在谈论数字和日期,则需要CultureInfo.InvariantCulture

但听起来你在谈论结构化数据,并且你希望能够反序列化这些数据。因此,您应该在其字符串表示中考虑该数据的格式

XML和JSON是序列化格式的流行选择。在现代.NET应用程序中,XML通常使用the XDocument classDataContractSerializer实现。使用the JSON.NET library可以最好地实现JSON。

答案 3 :(得分:0)

基于@Plutonix评论这是我选择的答案

System.Reflection.FieldInfo[] fields = obj.GetType().GetFields();
foreach (System.Reflection.FieldInfo info in fields) {
    object fieldValue = info.GetValue(obj);
    if (fieldValue != null) {
        System.Type type = fieldValue.GetType();
        string s = System.ComponentModel.TypeDescriptor.GetConverter(
            type).ConvertToInvariantString(fieldValue);
        ...
    }
}

相反
string s = System.ComponentModel.TypeDescriptor.GetConverter(
               type).ConvertToInvariantString(fieldValue);

object o = System.ComponentModel.TypeDescriptor.GetConverter(
               type).ConvertFromInvariantString(s);

This test seems to work