C# 格式化程序是否需要写入成员';在执行序列化时,流的名称是?
我正在读一本书,书中谈到使用C# 格式化程序是否需要写入成员';在执行序列化时,流的名称是?,c#,.net,C#,.net,我正在读一本书,书中谈到使用BinaryFormatter进行运行时序列化,以下步骤摘自该书: 格式化程序调用FormatterServic upes的GetSerializableMembers方法 此方法使用反射来获取类型的公共和私有实例字段(不包括使用NonSerializedAttribute属性标记的任何字段)。该方法返回MemberInfo对象数组,每个可序列化实例字段一个 然后将要序列化的对象和System.Reflection.MemberInfo对象数组传递给Formatter
BinaryFormatter
进行运行时序列化,以下步骤摘自该书:
[Serializable]
class Person {
public int age = 20;
public string name = "John";
...
}
作者说格式化程序需要将每个成员的名称和值写入流,因此在本例中,格式化程序需要将20个“John”、“age”、“name”写入流
但我觉得没有必要在流中写入成员的名称,写入值就足够了。因为如果您查看反序列化方法的核心:FormatterServices的PopulateObjectMembers方法
//我的简化版
公共静态对象PopulateObjectMembers(对象obj、成员信息[]成员、对象[]数据){
...
MemberInfo mi;
对于(inti=0;i来说,你把两个共同工作的东西混在一起了:
在一个站点上,有Serializable
属性及其方法。它还包含两个方法GetSerializableMembers()
来描述结构,以及GetObjectData()
来获取应序列化的活动实例的具体值。无论使用哪种编写器(也称为格式化程序)您总是需要一个键值对树,将属性名作为键,将其内容作为值(可能是键值对的另一个对象)
下一个发挥作用的是(在你的情况下)二进制格式化程序。它使用这种结构并选择它喜欢的任何东西,将信息写入某种流中。fomatter的这种特殊实现是为了优化流中所需的大小。这将通过省略键和只写入值以及假设读者知道确切的结构来实现cture并将值写入正确的属性
这就是为什么不应该使用此格式化程序的原因。相反,请使用某种也包含XML或JSON等结构的序列化。这些序列化还向流中添加键,使数据反序列化变得更容易,即使目标结构不完全匹配。您可能需要阅读以下内容:。引号:“BinaryFormatter类型很危险,不建议用于数据处理。应用程序应尽快停止使用BinaryFormatter
”如果不写入属性的名称,如何将其反序列化回正确的属性?可能会保存一个V1文件(具有两个属性)并反序列化到一个V2程序中,该程序有3个属性。如果不存储属性名,则不知道如何进行反序列化。@Neil,但它看起来像是FormatterServices。PopulateObjectMembers(对象obj,MemberInfo[]成员,对象[]数据)
方法不使用成员名,对象[]数据
仅包含值,但看起来像MemberInfo[/members
和object[]数据
具有一对一的关系,因此只要字段按顺序序列化,并且格式化程序按相同顺序反序列化字段,我们根本不需要序列化成员
,因为在反序列化过程中我们可以从类型中获得相同的成员?是的,你是对的。但这就是BinaryFormatter的问题。如果你使用c由于改变了被转移对象的结构,整个系统就解体了。
public static Object[] GetObjectData(Object obj, MemberInfo[] members);
[Serializable]
class Person {
public int age = 20;
public string name = "John";
...
}
// simplified version by me
public static object PopulateObjectMembers(object obj, MemberInfo[] members, object[] data) {
...
MemberInfo mi;
for (int i=0; i<members.Length; i++) {
mi = members[i];
if (data[i]!=null)
SerializationSetValue(mi, obj, data[i]);
}
...
return object;
}