【问题标题】:Why are properties without a setter not serialized为什么没有设置器的属性没有序列化
【发布时间】:2012-11-04 06:28:07
【问题描述】:

我有一个可序列化的类,我的类中的一个属性在 getter 中生成一个Guid。该属性不实现 setter,并且在序列化期间被忽略。为什么会这样?我是否总是必须实现一个 setter 才能序列化我的属性。

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
    }
}

我尝试实现一个空的 setter,它被正确序列化了。

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
        set {}
    }
}

更新:

你能指出我应该如何定义值永远不会改变的属性或值是在内部生成的吗?

【问题讨论】:

标签: c# .net xml-serialization


【解决方案1】:

请参阅 MSDN 文档中的“Introducing XML Serialization”。除其他外,它说:

可以序列化的项目

可以使用 XmlSerializer 类对以下项目进行序列化:

Public read/write properties and fields of public classes.

Classes that implement ICollection or IEnumerable.

注意:

Only collections are serialized, not public properties.
XmlElement objects.

XmlNode objects.

DataSet objects.

另请参阅“Why XML-Serializable class need a parameterless constructor”


另外,IXmlSerializable

除了上述可以被 XML Serializer 序列化的类型外,任何实现了 IXmlSerializable 接口的类型都可以进行序列化和反序列化。特别是,这意味着 XElement 和 XDocument 类型可以被序列化。

见“IXmlSerializable Interface”。

【讨论】:

    【解决方案2】:

    如果你想拥有私有的setter,并让对象可序列化/可反序列化,实现ISerializable,并创建一个像MyObject(SerializationInfo info,StreamingContext context)这样的构造函数。一个example is found here。

    【讨论】:

      【解决方案3】:

      XMLSerializer 的限制 - 没有 setter 的属性无法序列化。

      但是你可以使用DataContractSerializer序列化private setter properties-

      [DataMember]
      public string Id
      {
          get
          {
               return Guid.NewGuid().ToString();
          }
          private set {}
      }
      

      【讨论】:

      • 该属性应该被序列化为 xml 属性(参见原始帖子)。您的代码(DataMember 属性)生成一个 xml 元素。据我所知,没有(干净的)方法可以告诉 DataContractSerializer 将属性转换为属性而不是元素。 DataContractSerializer 很好,但您必须始终牢记这一限制。
      【解决方案4】:

      序列化属性用于序列化和反序列化对象。 XmlSerializer 将假定您不需要序列化任何没有设置器的属性。 将字符串反序列化为对象时将使用 Setter,因为需要创建对象的实例,然后使用 setter 填充属性值。

      【讨论】:

        【解决方案5】:

        这是XmlSerializer 的一个限制,它不会序列化只读属性,您在第二个示例中所做的基本上是对其进行序列化的黑客攻击,但是,如果您稍后需要它反序列化,它是无用的。

        您也可以改用DataContractSerializer,它更灵活。

        【讨论】:

        • DataContractSerializer 也需要设置器。这是一个限制,因为即使我们可能只将它用于一种类型的操作,比如反序列化,但声明需要同时用于两种操作,否则,序列化过程在尝试序列化一个值时将不知道如何处理一个值XML 转换成对象。
        • @ryadavilli 标记为[DataMember] 的任何内容都使用DataContractSerializer 进行序列化(只读或非只读)。
        • @James 我写了上面的内容,因为我在尝试相同的时候遇到了一些编译时错误。现在,当我回到我的代码并删除了 setter 时,它似乎编译得很好。这很奇怪,可能是我的功课,需要对此进行更多研究。
        • 啊啊啊终于找到我困惑的根源了。序列化不需要属性设置器。但是,如果属性没有设置器,则 XML 不会反序列化为对象。到这里,作业完成了。
        • @ryadavilli 没错,这只是XmlSerializer 实现的一个限制,它依赖于公共设置方法。 DataContractSerializer 在这个意义上更聪明一些(可能使用反射在幕后设置字段)。
        猜你喜欢
        • 2013-04-10
        • 2015-09-10
        • 1970-01-01
        • 2010-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多