在 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.345
或12,345
,具体取决于区域性设置。
是否有其他一些非区域性敏感的ToString
我可以调用基元类型?
另外,是否有对对象函数的非区域性敏感的通用字符串。我目前正在使用
object value = System.Convert.ChangeType(string, someType);
但这显然也是文化敏感的。 :(
对于 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);
这个测试似乎有效