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

本文关键字:序列化 安全 是什么 方法 字符串 转换 | 更新日期: 2023-09-27 18:32:48

>我想在 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);

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

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

对于 ChangeType,有一个重载,它接受 IFormatProvider,因此您可以调用:

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

对于基元类型,是否有其他一些非区域性敏感的 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()。它只是要编写的代码更少。:)

如果你在谈论数字和日期,你想要CultureInfo.InvariantCulture

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

XML 和 JSON 是序列化格式的常用选择。 在现代 .NET 应用程序中,XML 通常使用 XDocument 类或 DataContractSerializer 实现。 JSON 最好通过 JSON.NET 库实现。

根据@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);

这个测试似乎有效