【问题标题】:ShouldSerialize pattern and DataContractSerializerShouldSerialize 模式和 DataContractSerializer
【发布时间】:2012-07-09 12:00:19
【问题描述】:

有没有办法让ShouldSerialize* 模式与DataContractSerializer 一起使用?

这是一个小例子:

我有一个简单的类Person,看起来像这样:

[DataContract]
public class Person
{
  [DataMember]
  public string FirstName { get; set; }
  public bool ShouldSerializeFirstName()
  {
    return !string.IsNullOrEmpty(FirstName);
  }

  [DataMember]
  public string LastName { get; set; }
  public bool ShouldSerializeLastName()
  {
    return !string.IsNullOrEmpty(LastName);
  }

  public Person(string firstName, string lastName)
  {
    FirstName = firstName;
    LastName = lastName;
  }
  public Person(string firstName)
  {
    FirstName = firstName;
  }
  public Person()
  {
  }
}

FirstNameLastName 只有在它们不为空或不为空时才应序列化。这适用于XmlSerializer,但DataContractSerializer 似乎忽略了ShouldSerialize 模式。 *Specified 模式也不起作用。

我正在创建两个不同的 Xml 文件。一个带有 DataContractSerializer,一个带有 XmlSerializer:

List<Person> persons = new List<Person>();
persons.Add (new Person("John", "Doe"));
persons.Add (new Person("Carl"));

DataContractSerializer serializer = new DataContractSerializer (typeof (List<Person>));
using (XmlWriter writer = XmlWriter.Create(@"c:\test1.xml", settings))
{
  serializer.WriteObject (writer, persons);
}

XmlSerializer xmlSerializer = new XmlSerializer (typeof (List<Person>));
XmlWriter xmlWriter = XmlWriter.Create (@"c:\text2.xml", settings);
xmlSerializer.Serialize (xmlWriter, persons);
xmlWriter.Close();

文件test1.xml (DataContractSerializer) 的输出如下所示:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfPerson xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/XmlSerialization">
  <Person>
    <FirstName>John</FirstName>
    <LastName>Doe</LastName>
  </Person>
  <Person>
    <FirstName>Carl</FirstName>
    <LastName i:nil="true" />
  </Person>
</ArrayOfPerson>

文件test2.xml (XmlSerializer) 的输出如下所示:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfPerson xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Person>
    <FirstName>John</FirstName>
    <LastName>Doe</LastName>
  </Person>
  <Person>
    <FirstName>Carl</FirstName>
  </Person>
</ArrayOfPerson>

【问题讨论】:

    标签: c# datacontractserializer


    【解决方案1】:

    AFAIK,ShouldSerialize* 不适用于数据合同序列化程序。凯文的回答是没用的。你可以删除它。 不幸的是,给出的代码只有在处理空值时才有效。

    这是一个更通用的解决方案:它根据给定条件返回空值。

        [DataContract]
        public class Person
        {
          private string firstName;
          [DataMember(IsRequired = false, EmitDefaultValue = false)]
          public string FirstName
          {
            get
            {
                //Put here any condition for serializing
                return string.IsNullOrWhiteSpace(firstName) ? null : firstName;
            }
            set
            {
                firstName = value;
            }
          }
        }
    

    【讨论】:

    • 这应该是选择的答案。
    【解决方案2】:

    您应该在 DataMember 上设置 IsRequired 属性:

    [DataContract]
    public class Person
    {
      [DataMember(IsRequired = False, EmitDefaultValue = False)]
      public string FirstName { get; set; }
      ...
    }
    

    【讨论】:

    • 这似乎不起作用。这些属性仍然会被序列化,尽管它们是空的。
    • 将 EmitDefaultValue = false, 也添加到该列表(在 SSCE 中也已更改)。
    • 解决方案并不完全等同于 ShouldSerialize*()。使用后者,即使它是默认值,我也可以显式写入值,并且我可以抑制不等于默认值的值,一切都基于运行时的其他一些变量。无论如何+1,因为它很有帮助(而不是您的错,我们将由一个软件供应商生产的所有这些不同的序列化技术和概念搞得一团糟)。
    • ShouldSeralize* 不适用于 DataContractSerializer。这个答案具有误导性,从不调用 ShouldSeralize 方法。这种“有效”的唯一原因是ShouldSerializeFirstName() 中的逻辑对于 DataMember 属性的参数提供的功能是多余的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-02
    • 2010-11-13
    • 2016-10-16
    • 1970-01-01
    • 2011-07-13
    相关资源
    最近更新 更多