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 在应用程序之间工作