在C#中,什么';将原语转换为字符串进行序列化的安全方法是什么?
我想在C#中对类/结构进行一般序列化。为了简单起见,让我们假设类/结构只能有一层深度(没有结构的结构) 这是我想写的在C#中,什么';将原语转换为字符串进行序列化的安全方法是什么?,c#,string,serialization,deserialization,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) {
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()
对区域性敏感。换句话说,对于单个
,它可能会输出12.345
或12345
,具体取决于区域性设置
是否有其他非区域性敏感的ToString
I可以调用基元类型
此外,还有一个非区域性敏感的通用字符串到对象函数。我目前正在使用
object value = System.Convert.ChangeType(string, someType);
但这显然也是文化敏感的(对于ChangeType,有一个
System.Convert.ChangeType(string, someType, CultureInfo.InvariantCulture);
是否有其他非区域性敏感的字符串可以调用基本类型?
另外,是否存在非区域性敏感的通用字符串到对象函数
依我看,最简单的解决方案就是格式化字符串并传递一个格式化程序。这样你就不必显式地分别处理每个单独的值
例如:
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通常使用或实现。JSON的最佳实现方式是。基于@puropoix comment,这是我选择的答案
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);
是
使用
TypeDescriptor.GetConverter
然后可以对类型的值使用ConvertToInvariantString
非常简洁的解决方案,请注意,复合格式系统也通过以下方式处理空值—“如果要格式化的值为空,则返回空字符串(“”)”,这样代码就更少了!没错。我甚至没有想到那部分,但你是对的……我也可以去掉null
检查。我想我会的另一个方向呢?对不起…我在问题中没有看到任何反序列化的请求。不幸的是,反序列化是完全不同的。您没有处理对象实例(即,可以提供多态解析实现的对象实例),您必须知道要反序列化所处理的类型。好的一面是,这意味着您可以始终将CultureInfo.InvariantCulture
传递给相应的解析/反序列化方法,以反转上面的序列化操作。谢谢,但由于各种原因,我不能使用JSON.NET库或XML内容。@gman-发明全新的序列化格式比看起来更难,所以至少要考虑为什么现有的方法是这样做的:)如果你不喜欢文本格式的冗长——也许现有的二进制格式会是什么?请给我一些信任。我宁愿使用现有的解决方案。我看了看。它们不符合我的需要。例如为了处理多态类型,JSON.NET需要LINQ特性。但是我在Unity3D中使用的是C#.NET 2.0,它不支持LINQ。我的需求很小。我并不是在试图发明一个完整的100%序列化的解决方案。同时,如果有一种通用的C#方法来处理原语,我想知道它是什么。
object o = System.ComponentModel.TypeDescriptor.GetConverter(
type).ConvertFromInvariantString(s);