DataContract, default DataMember value
Asked Answered
M

3

23

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
    }
}
Meed answered 19/12, 2011 at 19:12 Comment(0)
A
22

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();
  }
}
Aviv answered 19/12, 2011 at 20:27 Comment(4)
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.Meed
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.Aviv
You can use nullable types to get around int and null ,plz check my updated ansAviv
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.Meed
W
8

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?

Wishbone answered 22/4, 2015 at 20:51 Comment(1)
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".Prototrophic
T
2

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.

Tullius answered 19/12, 2011 at 19:16 Comment(1)
No, this does not work (just tested it). The Deserializer overrides your default value, even if that value is not present in XML.Prototrophic

© 2022 - 2024 — McMap. All rights reserved.