【问题标题】:DataContract, default DataMember valueDataContract,默认 DataMember 值
【发布时间】: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
    }
}

【问题讨论】:

    标签: c# wcf datacontract datamember


    【解决方案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 中不存在该值
    猜你喜欢
    • 2020-09-05
    • 2011-08-18
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    相关资源
    最近更新 更多