C# 格式化程序是否需要写入成员';在执行序列化时,流的名称是?

C# 格式化程序是否需要写入成员';在执行序列化时,流的名称是?,c#,.net,C#,.net,我正在读一本书,书中谈到使用BinaryFormatter进行运行时序列化,以下步骤摘自该书: 格式化程序调用FormatterServic upes的GetSerializableMembers方法 此方法使用反射来获取类型的公共和私有实例字段(不包括使用NonSerializedAttribute属性标记的任何字段)。该方法返回MemberInfo对象数组,每个可序列化实例字段一个 然后将要序列化的对象和System.Reflection.MemberInfo对象数组传递给Formatter

我正在读一本书,书中谈到使用
BinaryFormatter
进行运行时序列化,以下步骤摘自该书:

  • 格式化程序调用FormatterServic upes的GetSerializableMembers方法
  • 此方法使用反射来获取类型的公共和私有实例字段(不包括使用NonSerializedAttribute属性标记的任何字段)。该方法返回MemberInfo对象数组,每个可序列化实例字段一个

  • 然后将要序列化的对象和System.Reflection.MemberInfo对象数组传递给FormatterServices的静态GetObjectData方法:
  • 格式化程序将程序集的标识和类型的全名写入流

  • 然后,格式化程序对两个数组中的元素进行枚举,将每个成员的名称写入流

  • 我对第四步有个问题。让我们以一个具体的类型为例:

    [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;
    }