为什么 XmlSerializer 这么难用? [英] Why is XmlSerializer so hard to use?

查看:27
本文介绍了为什么 XmlSerializer 这么难用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想像这样使用 XML 序列化:

I imagine to use XML serialization like this:

class Foo {
    public Foo (string name) {
        Name1 = name;
        Name2 = name;
    }

    [XmlInclude]
    public string Name1 { get; private set; }

    [XmlInclude]
    private string Name2;
}

StreamWriter wr = new StreamWriter("path.xml");
new XmlSerializer<Foo>().Serialize (wr, new Foo ("me"));

我知道这段代码是错误的.只是为了展示我想如何使用它.

I know this code is wrong. It was just to display how I would like to use it.

但这根本不起作用:

  • XmlSerializer 不是通用的.我必须对(反)序列化进行转换和反对.
  • 每个属性都必须完全公开.为什么我们不只是使用反射来访问私有 setter?
  • 私有字段无法序列化.我想用一个属性装饰私有字段,让 XmlSerializer 包含它们.

我是否遗漏了什么,而 XmlSerializer 实际上提供了所描述的可能性?是否有替代 XML 的序列化程序可以更复杂地处理这些情况?

Did I miss something and XmlSerializer is actually offering the described possibilities? Are there alternate serializers to XML that handle these cases more sophisticatedly?

如果不是:我们毕竟是在 2010 年,而 .NET 已经存在很多年了.XML 序列化经常被使用,完全标准并且应该很容易执行.或者我的理解可能是错误的,并且 XML 序列化不应该有充分的理由公开所描述的功能?

If not: We're in 2010 after all, and .NET has been around for many years. XML serialization is often used, totally standard and should be really easy to perform. Or is my understanding possibly wrong and XML serialization ought not to expose the described features for a good reason?

传统不是 imo 的好理由.List起初也是非泛型的.

Legacy is not a good reason imo. Listwas nongeneric at first, too.

(随意调整标题或标签.如果这应该是 CW,请留下注释.)

(Feel free to adjust caption or tags. If this should be CW, please just drop a note.)

推荐答案

首先是固定代码,然后是问题的答案:

First the fixed code, then the answers to your questions:

public class Foo {
    public Foo() : this("") {}
    public Foo (string name) {
        Name1 = name;
        Name2 = name;
    }
    // note only this will be serialized
    public string Name1 { get; private set; }
    // this won't
    private string Name2;
}

或在 3.0 中:

[DataContract]
class Foo {
    public Foo (string name) {
        Name1 = name;
        Name2 = name;
    }
    [DataMember]
    public string Name1 { get; private set; }
    [DataMember]
    private string Name2;
}

(并使用 DataContractSerializer 而不是 XmlSerializer)

(and use DataContractSerializer instead of XmlSerializer)

XmlSerializer 不是通用的.我必须对(反)序列化进行转换和反对.

XmlSerializer is not generic. I have to cast from and to object on (de)serialization.

这对于序列化器来说很常见.我有自己的序列化程序,最初我确实使它完全通用.结果证明这是一个很大的设计错误.巨大的.不,认真的.我目前正在重新编写每一行代码以将其关闭.

That is common for serializers. I have my own serializer, and initially I did make it fully generic. And it turned out to be a big design mistake. Huge. No, seriously. I'm currently in the process of re-writing every line of code to switch it out.

简单的;序列化程序通常涉及某种程度的反射(对于代码生成或实际工作,取决于实现).反射和泛型不能很好地发挥作用,尤其是在 WCF 等一些框架上.让你的代码做最后的转换是一个公平的妥协.如果你真的想要,我有一个数量的关于这个的博客条目......

Simply; serializers generally involve some level of reflection (either for code-gen or for the actual work, depending on the implementation). Reflection and generics don't play nicely, especially on some of the frameworks like WCF. Having your code do the final cast is a fair compromise. I have a number of blog entries on this if you really want...

每个属性都必须完全公开.

Every property has to be fully public.

这确实是 XmlSerializer 的一个限制(虽然一个列表/集合 没有 一个 setter 就可以了,如果你有一个抛出公共获取和私有设置).此外,类型需要是公共的,并且有一个无参数的构造函数.

That is indeed a limitation of XmlSerializer (although a list/colletion without a setter is fine, it will throw if you have a public get and private set). Also, the type needs to be public and have a parameterless constructor.

为什么我们不只是使用反射来访问私有 setter?

Why aren't we just using Reflection to access private setters?

为了性能,XmlSerializer 动态构建程序集以执行您想要的操作.它无法自动访问您的代码内部.有关信息,我正在做类似的事情,但我提供 2 个级别的生成;完全静态的(进入可部署的 dll),然后它只能与公共成员或内存中一起使用, 仍然可以访问私有成员.我猜他们只想确定一个模型,这是有道理的 - 他们需要sgen",这决定了第一个模型.

For performance, XmlSerializer builds an assembly on the fly to do what you want. It doesn't have automatic access to your code's internals. For info, I'm doing something similar but I offer 2 levels of generation; fully static (into a deployable dll), which then only works with public members, or in-memory, which can still access private members. I guess they wanted to settle on only 1 model, which makes sense - and they needed "sgen", which dictates the first model.

私有字段无法序列化.我想用一个属性装饰私有字段,让 XmlSerializer 包含它们.

Private fields cannot be serialized. I'd like to decorate private fields with an attribute to have XmlSerializer include them.

然后使用DataContractSerializer,它将序列化任何标记为[DataMember]的成员(包括私有的).

Then use DataContractSerializer, which will serialize any member (including private) marked [DataMember].

这篇关于为什么 XmlSerializer 这么难用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆