DataContract, default DataMember value

24,858

Solution 1

You can use [OnDeserialized]

Use the OnDeserializedAttribute when you need to fix values on a deserialized object after it has been deserialized and before the graph is returned.

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

EDIT: From your Comments

For bool or int you can use nullable bool and nullable int so if these age and Single attributes are missing in xml file then they will be null as well.

here is quick sample I prepared

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();
  }
}

Solution 2

use [OnDeserializing()]

and you set your values BEFORE the deserialization. So there is no check necessary, which could go wrong - what if the mAge was serialized to be 0?

Solution 3

This should work.

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

Take a look at this page.

Share:
24,858
BuzBuza
Author by

BuzBuza

C++ Developer in a networking compagny

Updated on July 09, 2020

Comments

  • BuzBuza
    BuzBuza almost 4 years

    Is there a way to choose default values of attributes that are not in the xml file during deserialization?
    If the mAge attribute is not present in the xml file, I want to use a default value of 18. Is it possible ?

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

    Edit to put the answer.

    [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
        }
    }
    
  • BuzBuza
    BuzBuza over 12 years
    I can use your answer if I want to override the value of an object, because when the reference is set to null I know that the attribut is not present in the xml File. But how can I know if a boolean or an int attribut is present in the xml file ? If the value for a bolean is set to false or an int is set to 0. I can't distingue beetwen unseted attribut and attribut seted to default c# value.
  • Surjit Samra
    Surjit Samra over 12 years
    As deserilization will try to set default values for missing data in a given structure so your only option is to check for valid values eg as I updated my answer and checking for if age mAge == 0 then set your value.
  • Surjit Samra
    Surjit Samra over 12 years
    You can use nullable types to get around int and null ,plz check my updated ans
  • BuzBuza
    BuzBuza over 12 years
    Thks you, your answer solve my issue. Using nullable types and System.Runtime.Serialization.OnDeserialized function isbrilliant idea. My post is edited to give the answers.
  • Patrick Stalph
    Patrick Stalph over 7 years
    No, this does not work (just tested it). The Deserializer overrides your default value, even if that value is not present in XML.
  • Patrick Stalph
    Patrick Stalph almost 7 years
    When you deserialize simple types (e.g. double) or structs this is the correct way to go. Before deserialization you set optional fields to some app-specific default (or invalid value, e.g. double.NaN). Deserialization will overwrite all values given in the XML file and leave others untouched. After deserialization you cannot distinguish a zero value "set from XML" and a zero value "not being set".