【发布时间】:2009-02-10 11:04:02
【问题描述】:
是否有可能使用 XmlSerializer 将其数据反序列化为类的现有实例而不是新实例?
这在两种情况下会有帮助:
- 轻松将两个 XML 文件合并到一个对象实例中。
- 让对象构造器本身成为从 XML 文件加载其数据的人。
如果默认情况下不可能,它应该通过使用反射(在反序列化后复制每个属性)来工作,但这将是一个丑陋的解决方案。
【问题讨论】:
标签: c# .net serialization .net-2.0
是否有可能使用 XmlSerializer 将其数据反序列化为类的现有实例而不是新实例?
这在两种情况下会有帮助:
如果默认情况下不可能,它应该通过使用反射(在反序列化后复制每个属性)来工作,但这将是一个丑陋的解决方案。
【问题讨论】:
标签: c# .net serialization .net-2.0
基本上,你不能。 XmlSerializer 是严格建设性的。自定义 XmlSerializer 唯一有趣的事情是实现 IXmlSerializable 并自己做所有事情 - 这不是一个有吸引力的选择(它仍然会使用默认构造函数等创建新实例)。
xml 是严格要求吗?如果您可以使用不同的格式,protobuf-net 支持将片段合并到现有实例中,就像:
Serializer.Merge(source, obj);
【讨论】:
我认为您在 Reflection 的想法上走在了正确的轨道上。
由于您可能对 XML 操作有一个包装器,因此您可以获取目标对象,将反序列化正常地转换为一个新对象,然后通过一个一个地复制仅包含非默认值。
实现它不应该那么复杂,并且它会像就地反序列化一样从应用程序的其余部分中查看消费者。
【讨论】:
几周前我遇到了同样的问题。
我在我的一个实体类实现的ISelfSerializable接口中放了一个Deserialize(string serialized form)方法。我还确保接口强制类具有默认构造函数。
在我的工厂中,我创建了一个该类型的对象,然后将字符串反序列化到其中。
【讨论】:
这不是线程安全的事情......但你可以这样做:
[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 中写入的任何内容。
【讨论】: