【问题标题】:How to differentiate between not set and set to null during XML Serialization?XML序列化期间如何区分未设置和设置为null?
【发布时间】:2014-04-08 16:07:29
【问题描述】:

我有一个允许外部应用程序更新我的数据库的 WCF 服务。我有一个更新操作合同,它接受外部应用程序应该设置的数据合同。我的问题是我无法区分设置为 null 和实际未设置的内容,因为当数据协定被序列化时,值始终为 null。考虑以下数据协定:

[DataContract, XmlRoot("Person")]
public class Person: BaseEntity
{
    [DataMember, XmlElement]
    public string Prefix { get; set; }
    [DataMember, XmlElement]
    public string FirstName { get; set; }
    [DataMember, XmlElement]
    public string MiddleName { get; set; }
    [DataMember, XmlElement]
    public string LastName { get; set; }
    [DataMember, XmlElement]
    public string MaidenName { get; set; }
    [DataMember, XmlElement]
}

一个外部应用程序只能设置 FirstName 和 LastName 而忽略其余属性。但是当我的 WCF 服务收到请求时,其他属性设置为 null。所以我的 WCF 服务中的更新 statememt 会认为那些属性设置为空。我希望找到一种方法来确定未设置属性,以便我的更新语句可以忽略这些属性。

【问题讨论】:

  • 另请咨询this related post
  • Adam,很遗憾我不打算手动解析 xml 并依赖 XML 序列化。并且一个没有设置或者设置为null的XML元素,总是会被反序列化一样的,也就是null

标签: c# .net wcf xml-serialization


【解决方案1】:

你无法区分这两种情况。每个变量都以一个初始值开始其生命周期,null 用于引用类型,0 用于整数和浮点数等等。因此,两者之间绝对没有区别

String firstName;

String firstName;

firstName = null;

这意味着如果您需要此信息,则必须手动执行跟踪。

String firstName;
Boolean firstNameSet;

firstName = null;
firstNameSet = true;

请注意,手动我的意思是您必须手动跟踪该信息,您当然可以向您的属性设置器添加一些跟踪代码,这样您班级的用户就不必知道这一点。

public class Person
{
   private String firstName = null;

   private Boolean firstNameSet = false;

   private String lastName = null;

   private Boolean lastNameSet = false;

   public String FirstName
   {
      get { return this.firstName; }
      set
      {
         this.firstName = value;
         this.firstNameSet = true;
      }
   }

   public String LastName
   {
      get { return this.lastName; }
      set
      {
         this.lastName = value;
         this.lastNameSet = true;
      }
   }
}

还有很多其他替代方法可以实现这一点,例如,您可以使用集合来跟踪集合属性。最佳解决方案显然取决于您的要求。

public class Person
{
   private readonly ISet<String> setProperties = new HashSet<String>();

   private String firstName = null;

   private String lastName = null;

   public String FirstName
   {
      get { return this.firstName; }
      set
      {
         this.firstName = value;
         this.setProperties.Add("FirstName");
      }
   }

   public String LastName
   {
      get { return this.lastName; }
      set
      {
         this.lastName= value;
         this.setProperties.Add("LastName");
      }
   }
}

【讨论】:

  • 但是我的 getter/setter 也暴露为数据合约。一旦序列化然后反序列化,我们不会丢失跟踪代码吗?
  • 为简单起见,我将跟踪字段设为私有变量,但您当然也必须对它们进行序列化和反序列化。碰巧我最后一次接触 WCF 是在一段时间前,我无法从头顶上提供一个好的工作解决方案,所以我忽略了所有 WCF 特定的部分,只是想提出一个粗略的想法。如何最好地序列化跟踪字段、跟踪属性或跟踪字典,您必须自己弄清楚。
【解决方案2】:

我最终改为创建自定义类:

[DataContract, XmlRoot("Person")]
public class Person: BaseEntity
{
    [DataMember, XmlElement]
    public DomainString Prefix { get; set; }
    [DataMember, XmlElement]
    public DomainString FirstName { get; set; }
    [DataMember, XmlElement]
    public DomainString MiddleName { get; set; }
    [DataMember, XmlElement]
    public DomainString LastName { get; set; }
    [DataMember, XmlElement]
    public DomainString MaidenName { get; set; }
}

public class DomainString{
    public string Value {get; set;}
    public bool IsNull {get; set;}
}

因此,在我的 wcf 客户端中,我可以执行 ff.差异化:

如果 person.LastName == null,则未设置姓氏。 如果 person.LastName.IsNull ,则 lastname 设置为 null。

【讨论】:

    猜你喜欢
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-25
    相关资源
    最近更新 更多