DataContract,默认的DataMember值

23

在反序列化期间,是否有一种方法可以选择那些不在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
    }
}
3个回答

22

您可以使用[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;
    }
  }
}

编辑:来自您的评论

对于布尔值或整数,您可以使用可空布尔值和可空整数,因此如果xml文件中缺少这些age和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文件中?如果布尔值的值设置为false或整数设置为0,则无法区分未设置的属性和设置为默认c#值的属性。 - BuzBuza
由于反序列化将尝试为给定结构中缺失的数据设置默认值,因此您唯一的选择是检查有效值,例如,我更新了我的答案并检查年龄mAge == 0,则设置您的值。 - Surjit Samra
你可以使用可空类型来解决 int 和 null 的问题,请查看我的更新答案。 - Surjit Samra
谢谢你,你的回答解决了我的问题。使用可空类型和System.Runtime.Serialization.OnDeserialized函数是一个很棒的想法。我已经编辑了我的帖子来提供答案。 - BuzBuza

8

使用 [OnDeserializing()],在反序列化之前设置您的值。因此不需要进行检查,以免出现错误 - 如果 mAge 序列化为 0 呢?


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

2

这应该可以运行。

[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; }
  };

请查看这个页面。


2
不,这不起作用(刚测试过)。反序列化程序会覆盖您的默认值,即使该值在 XML 中不存在。 - Patrick Stalph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接