为了简化格式化器的操作,FCL在System.Runtime.Serialization命名空间提供了一个为了简化格式化器的操作,FCL在System.Runtime.Serialization命名空间提供了一个FormatterServices类型。该类型只包含静态方法,而且该类型不能实例化。
以下步骤描述了格式化器如何自动序列化类型应用了SerializableAttribute 特性的对象:
- 格式化器调用FormatterServices的GetSerializableMembers方法:
public static MemberInfo[] GetSerializableMembers(Type type, StreamingContext context) ;
这个方法利用反射获取类型的public和private实例字段(标记了NonSerializedAttribute特性的字段除外)。方法返回由MemberInfo对象构成的数组,其中每个元素都对应一个可序列化的实例字段。
-
对象被序列化,System.Reflection.MemberInfo 对象数组传给FormatterServices 的静态方法GetObjectData:
public static Object[] GetObjectData(object obj, MemberInfo[] members)
这个方法返回一个Object数组,其中每个元素都标识了被序列化的那个对象中的一个字段的值。这个Object数组和Memberlnfo数组是并行(parallel)的;换言之,Object数组中的元素0是MemberInfo数组中的元素0所标识的那个成员的值。
-
格式化器将程序集标识和类型的完整名称写入流中。
-
格式化器然后遍历两个数组中的元素,将每个成员的名称和值写入流中。
以下步骤描述了格式化器如何自动反序列化类型应用了SerializableAttribute 特性的对象:
- 格式化器从流中读取程序集标识和完整类型名称。如果程序集当前没有加载到AppDomain中,就加载它(这一点前 面已经讲过了)。如果程序集不能加载,就抛出一个SerializationException异常,对象不能反序列化。如果程序集已加载,格式化器将程序集标识信息和类型全名传给FormatterServices的静态方法GetTypeFromAssembly:
public static Type GetTypeFromAssembly(Assembly assem, String name);
这个方法返回一个System.Type对象,它代表要反序列化的那个对象的类型。
-
格式化器调用FormatterServices的静态方法GetUninitializedObject:
public static Object GetUninitializedObject(Type type);
这个方法为一个新对象分配内存,但不为对象调用构造器。然而,对象的所有字节都被初始化为成null或0。
-
格式化器现在构造并初始化--个MemberInfo数组,具体做法和前面一样,都是调用FormatterServices的GetSerializableMembers方法。这个方法返回序列化好、现在需要反序列化的一组字段。
-
格式化器根据流中包含的数据创建并初始化一个Object数组。
-
将新分配对象、MemberInfo数组以及并行Object数组(其中包含字段值)的引用传给FormatterServices的静态方法PopulateObjectMembers:
public static Object PopulateObjectMembers(Object obj, MemberInfo[] members, Object[] data);
这个方法遍历数组,将每个字段初始化成对应的值。到此为止,对象就算是被彻底反序列化了。