如何使用XmlSerializer反序列化为现有实例?
是否有可能使用XmlSerializer将其数据反序列化为现有的类实例而不是新的实例?
这在两种情况下会有所帮助:
- 轻松将两个XML文件合并到一个对象实例中。
- 让object constructer本身就是从XML文件加载数据的人。
如果默认情况下不可能,它应该使用reflection(在反序列化后复制每个属性),但这将是一个丑陋的解决方案。
我认为你的反思理念正在走上正轨。
既然你可能有一个围绕XML操作的包装器,你可以接收目标对象,通常将反序列化作为新对象,然后通过逐个复制只保存非默认值的属性来做类似于克隆的操作。
实现这一点应该不是那么复杂,并且它会从应用程序的其余部分看待消费者,就像就地反序列化一样。
基本上,你不能。 XmlSerializer
是严格的建设性的。 您可以自定义XmlSerializer
的唯一有趣的事情是实现IXmlSerializable
并自己完成所有事情 – 不是一个有吸引力的选项(它仍将使用默认构造函数创建新实例等)。
xml
是严格的要求吗? 如果您可以使用不同的格式, protobuf-net支持将片段合并到现有实例中,如下所示:
Serializer.Merge(source, obj);
几个星期前我遇到了同样的问题。
我在ISelfSerializable接口中添加了一个Deserialize(字符串序列化表单)方法,该接口是我实现的一个实体类。 我还确保接口强制类具有默认构造函数。
在我的工厂里,我创建了一个这种类型的对象,然后将字符串反序列化为它。
这不是线程安全的事情……但你可以这样做:
[Serializable] public class c_Settings { static c_Settings Default; public static SetExistingObject(c_Settings def) { Default = def; } public string Prop1; public bool Prop2; public c_Settings() { if (Default == null) return; MemberInfo[] members = FormatterServices.GetSerializableMembers(typeof(c_Settings)); FormatterServices.PopulateObjectMembers(this, members, FormatterServices.GetObjectData(Default, members)); } }
这样,您将对象提供给反序列化器和反序列化器只会覆盖.xml中写入的任何内容。