如何使用 XmlSerializer 反序列化到现有实例?

发布于 2024-07-13 14:21:38 字数 223 浏览 6 评论 0原文

是否可以使用 XmlSerializer 将其数据反序列化为类的现有实例而不是新实例?

这在两种情况下会很有帮助:

  1. 轻松地将两个 XML 文件合并到一个对象实例中。
  2. 让对象构造器本身成为从 XML 文件加载其数据的构造器。

如果默认情况下不可能,则应该通过使用反射来工作(在反序列化后复制每个属性),但这将是一个丑陋的解决方案。

Is it somehow possible to use the XmlSerializer to deserialize its data into an existing instance of a class rather than into a new one?

This would be helpful in two cases:

  1. Easily merge two XML files into one object instance.
  2. Let object constructer itself be the one who is loading its data from the XML file.

If the is not possible by default it should work by using reflection (copying each property after the deserialisation) but this would be an ugly solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

记忆里有你的影子 2024-07-20 14:21:38

基本上,你不能。 XmlSerializer 是严格构造性的。 自定义 XmlSerializer 唯一有趣的事情是实现 IXmlSerialized 并自己完成所有操作 - 这不是一个有吸引力的选项(并且它仍然会使用默认构造函数创建新实例, ETC)。

xml 是严格要求吗? 如果您可以使用其他格式,protobuf-net 支持将片段合并到现有实例中,就像这样简单:

Serializer.Merge(source, obj);

Basically, you can't. XmlSerializer is strictly constructive. The only interesting thing you can do to customize XmlSerializer is to implement IXmlSerializable and do everything yourself - not an attractive option (and it will still create new instances with the default constructor, etc).

Is xml a strict requirement? If you can use a different format, protobuf-net supports merging fragments into existing instances, as simply as:

Serializer.Merge(source, obj);
疏忽 2024-07-20 14:21:38

我认为你的反思想法是正确的。

由于您可能有一个围绕 XML 操作的包装器,因此您可以接收目标对象,通常将反序列化到一个新对象中,然后通过仅一一复制包含非默认值的属性来执行类似于克隆的操作。

实现它不应该那么复杂,它会像就地反序列化一样从应用程序的其余部分寻找消费者。

I think you're on the right track with the Reflection idea.

Since you probably have a wrapper around the XML operations anyway, you could take in the destination object, do the deserialization normally into a new object, then do something similar to cloning by copying over one by one only the properties holding non-default values.

It shouldn't be that complex to implement this, and it would look to consumers from the rest of your application just like in-place deserialization.

傲影 2024-07-20 14:21:38

几周前我遇到了同样的问题。

我在我的实体类实现的ISelfSerialized接口中放置了一个方法Deserialize(字符串序列化形式)。 我还确保接口强制该类具有默认构造函数。

在我的工厂中,我创建了该类型的对象,然后将字符串反序列化到其中。

I hit the same problem a few weeks ago.

I put a method Deserialize(string serialized form) in the ISelfSerializable interface that an entity class of mine implemented. I also made sure the interface forced the class to have a default constructor.

In my factory I created an object of that type and then deserialized the string into it.

拒绝两难 2024-07-20 14:21:38

这不是线程安全的事情...但您可以这样做:

[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 中写入的内容。

This is not thread safe thing to do... But you can do:

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

This way you feed your object to deserialiser and deserialiser only overwrites whatever is written in .xml.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文