我想在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);
但这显然也是文化敏感的。 :(
答案 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
class或DataContractSerializer
实现。使用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);