在C#中,自定义序列化机制有哪些实现方式,它们各自的工作原理和适用场景是什么?
考察说明
考查对C#序列化机制的理解,包括自定义序列化的实现方法、适用场景及底层原理。
回答思路
- 【回答框架 1】自定义序列化主要实现方式包括:实现ISerializable接口、使用序列化特性(如SerializableAttribute、DataContractAttribute)、自定义序列化代理(ISerializationSurrogate)、以及通过反射或流处理自行编写序列化逻辑。
- 【回答框架 2】ISerializable接口允许类控制自身的序列化,通过实现GetObjectData方法和带SerializationInfo、StreamingContext的特殊构造函数来填充和恢复数据。适用于需要精细控制序列化内容或处理版本兼容性的场景。
- 【回答框架 3】序列化特性(SerializableAttribute)配合BinaryFormatter进行序列化,控制字段的可访问性;DataContractSerializer则基于数据契约,与类型无关,更适合跨平台或服务通信。
- 【回答框架 4】自定义序列化代理(ISerializationSurrogate)允许为现有类型定制序列化过程,而无需修改类型本身,适用于第三方类型或需要特定格式的场景。
- 【回答框架 5】在不使用内置序列化器时,可以通过反射枚举字段并用JsonSerializer等手动构建对象图,实现完全自定义的序列化和反序列化,但需要处理循环引用、类型安全等复杂问题。
- 【关键点 1】实现ISerializable需要配套特殊构造函数,且构造函数的参数必须与GetObjectData中的顺序一致。
- 【关键点 2】DataContractSerializer要求类型标注DataContractAttribute,字段标注DataMemberAttribute,且序列化不依赖字段可访问性。
- 【关键点 3】ISerializationSurrogate依赖SurrogateSelector进行注册,并实现GetObjectData和SetObjectData方法。
- 【关键点 4】循环引用需通过ObjectManager处理,否则会导致序列化失败或无限递归。
- 【关键点 5】自定义序列化需要考虑版本兼容性,如字段增加或删除,得用版本号或兼容逻辑。
- 【易错点 1】使用ISerializable时,如果构造函数未正确处理,可能抛出SerializationException。
- 【易错点 2】BinaryFormatter序列化时未标记SerializableAttribute字段,会引发SerializationException。
- 【易错点 3】若自定义序列化逻辑涉及访问控制或敏感信息,需注意安全审计。