DataContract,默认 DataMember 值

Posted

技术标签:

【中文标题】DataContract,默认 DataMember 值【英文标题】:DataContract, default DataMember value 【发布时间】:2012-01-23 20:54:08 【问题描述】:

有没有办法在反序列化过程中选择xml文件中没有的属性的默认值? 如果xml文件中不存在mAge属性,我想使用默认值18。可以吗?

[DataContract]
public class Person 

    public Person ()
    
    
    [DataMember(Name = "Name")]
    public string mName  get; set; 
    [DataMember(Name = "Age")]
    public int mAge  get; set; 
    [DataMember(Name = "Single")]
    public bool mIsSingle  get; set; 
;

编辑以给出答案。

[DataContract]
public class Person 

    public Person ()
    
    
    [DataMember(Name = "Name")]
    public string mName  get; set; 
    [DataMember(Name = "Age")]
    public int? mAge  get; set; 
    [DataMember(Name = "Single")]
    public bool? mIsSingle  get; set; 

    [System.Runtime.Serialization.OnDeserialized]
    void OnDeserialized(System.Runtime.Serialization.StreamingContext c)
    
        mAge = (mAge == null ? 18 : mAge); // 18 is the default value
    

【问题讨论】:

【参考方案1】:

您可以使用[OnDeserialized]

使用 OnDeserializedAttribute 当你需要在一个 反序列化的对象在被反序列化之后和之前 返回图表。

[DataContract]
 public class Person 
  
    public Person ()
    
    
    [DataMember(Name = "Name")]
    public string mName  get; set; 
    [DataMember(Name = "Age")]
    public int mAge  get; set; 
    [DataMember(Name = "Single")]
    public bool mIsSingle  get; set; 



    [System.Runtime.Serialization.OnDeserialized]
    void OnDeserialized(System.Runtime.Serialization.StreamingContext c)
    
      mAge = (mAge == 0) ?18:mAge;
    
  

编辑:来自您的评论

对于 bool 或 int,您可以使用 nullable bool and nullable int 因此,如果 xml 文件中缺少这些年龄和 Single 属性,那么它们也将为空。

这是我准备的快速示例

using System.Runtime.Serialization;
using System.ServiceModel;
using MySpace;
using System.ServiceModel.Channels;
using System;
namespace MySpace


 [DataContract]
 public class Person 
  
    public Person ()
    
    
    [DataMember(Name = "Name")]
    public string mName  get; set; 
    [DataMember(Name = "Age")]
    public int? mAge  get; set; 
    [DataMember(Name = "Single")]
    public bool? mIsSingle  get; set; 



    [System.Runtime.Serialization.OnDeserialized]
    void OnDeserialized(System.Runtime.Serialization.StreamingContext c)
    
      mAge =  (mAge == null ? 18 : mAge);
    
  

[ServiceContract]
public interface IService

  [OperationContract]
  Person Method(Person dd);


public class Service : IService

  public Person Method(Person dd)
  
    return dd;
  


class Program

  static void Main(string[] args)
  
    string Url = "http://localhost:8000/";
    Binding binding = new BasicHttpBinding();
    ServiceHost host = new ServiceHost(typeof(Service));
    host.AddServiceEndpoint(typeof(IService), binding, Url);
    host.Open();
    ChannelFactory<IService> fac = new ChannelFactory<IService>(binding);
    fac.Open();
    IService proxy = fac.CreateChannel(new EndpointAddress(Url));
    Person d = new Person();
    d.mName = "BuzBuza";

    Console.WriteLine("Data before calling service " + (d.mAge == null ? " null " : d.mAge.Value.ToString()));
    Console.WriteLine("Data before calling service " + (d.mIsSingle == null ? "null" : d.mIsSingle.Value.ToString()));
    d = proxy.Method(d);
    fac.Close();
    host.Close();
    Console.WriteLine("Data after calling service " + (d.mAge == null ? " null " : d.mAge.Value.ToString()));
    Console.WriteLine("Data after calling service " + (d.mIsSingle == null ? "null" : d.mIsSingle.Value.ToString()));

    Console.ReadLine();
  

【讨论】:

如果我想覆盖对象的值,我可以使用您的答案,因为当引用设置为 null 时,我知道 xml 文件中不存在该属性。但是我怎么知道 xml 文件中是否存在 boolean 或 int 属性?如果布尔值设置为 false 或 int 设置为 0。我无法区分未设置的属性和设置为默认 c# 值的属性。 由于反序列化将尝试为给定结构中的缺失数据设置默认值,因此您唯一的选择是检查有效值,例如当我更新我的答案并检查 age mAge == 0 然后设置你的价值。 您可以使用可为空的类型来绕过 int 和 null ,请检查我更新的答案 谢谢你,你的回答解决了我的问题。使用可空类型和 System.Runtime.Serialization.OnDeserialized 函数是绝妙的想法。我的帖子经过编辑以给出答案。【参考方案2】:

使用[OnDeserializing()]

并且您在反序列化之前设置您的值。所以没有必要的检查,这可能会出错 - 如果 mAge 被序列化为 0 怎么办?

【讨论】:

当您反序列化简单类型(例如double)或结构时,这是正确的方法。在反序列化之前,您将可选字段设置为某些特定于应用程序的默认值(或无效值,例如double.NaN)。反序列化将覆盖 XML 文件中给出的所有值,而其他值保持不变。反序列化后,您无法区分“从 XML 中设置”的零值和“未设置”的零值。【参考方案3】:

这应该可行。

[DataContract]
 public class Person 
  
    public Person ()
    
    
    [DataMember(Name = "Name")]
    public string mName  get; set; 
    [DataMember(Name = "Age")]
    public int mAge = 18;
    [DataMember(Name = "Single")]
    public bool mIsSingle  get; set; 
  ;

看看this页面。

【讨论】:

不,这不起作用(刚刚测试过)。解串器会覆盖您的默认值,即使 XML 中不存在该值

以上是关于DataContract,默认 DataMember 值的主要内容,如果未能解决你的问题,请参考以下文章

DataContract,默认 DataMember 值将 api 在应用程序之间工作

WCF REST 服务中的响应时间问题非常重要_更多 10 分钟

如何找出类是不是具有 DataContract 属性?

包含异常的 DataContract

从 XSD 生成 DataContract