Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XmlSerializer define default value

We have an xml document with some user settings. We just added a new setting (which is not found in legacy xml documents) and the XmlSerializer automatically sets it to false. I tried DefaultValueAttribute but it doesn't work. Any idea on how I can get the default value to be true? This is the code:

private bool _property = true;
[DefaultValueAttribute(true)]
public bool Property 
{
    get { return _property; }
    set
    {
        if (_property != value)
        {
            _property = value;
            this.IsModified = true;
        }
    }
}

Thanks!

like image 826
Carlo Avatar asked Sep 03 '11 01:09

Carlo


2 Answers

DefaultValue affects the serialization insofar as if at runtime the property has a value that matches what the DefaultValue says, then the XmlSerializer won't actually write that element out (since it's the default).

I wasn't sure whether it would then affect the default value on read, but it doesn't appear to do so in a quick test. In your scenario, I'd likely just make it a property with a backing field with a field initializer that makes it 'true'. IMHO I like that better than ctor approach since it decouples it from the ctors you do or don't have defined for the class, but it's the same goal.

using System;
using System.ComponentModel;
using System.Xml.Serialization;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        var serializer = new XmlSerializer(typeof(Testing));

        string serializedString;
        Testing instance = new Testing();
        using (StringWriter writer = new StringWriter())
        {
            instance.SomeProperty = true;
            serializer.Serialize(writer, instance);
            serializedString = writer.ToString();
        }
        Console.WriteLine("Serialized instance with SomeProperty={0} out as {1}", instance.SomeProperty, serializedString);
        using (StringReader reader = new StringReader(serializedString))
        {
            instance = (Testing)serializer.Deserialize(reader);
            Console.WriteLine("Deserialized string {0} into instance with SomeProperty={1}", serializedString, instance.SomeProperty);
        }
        Console.ReadLine();
    }
}

public class Testing
{
    [DefaultValue(true)]
    public bool SomeProperty { get; set; }
}

As I mentioned in a comment, the page on the xml serialization attributes (http://msdn.microsoft.com/en-us/library/83y7df3e.aspx) claims that the DefaultValue will indeed make the serializer set the value when it's missing, but it doesn't do so in this test code (similar to above, but just deserializes 3 inputs).

using System;
using System.ComponentModel;
using System.Xml.Serialization;
using System.IO;

class Program
{
    private static string[] s_inputs = new[]
    {
        @"<?xml version=""1.0"" encoding=""utf-16""?>
          <Testing xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" />",

        @"<?xml version=""1.0"" encoding=""utf-16""?>
          <Testing xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
              <SomeProperty />
          </Testing>",

        @"<?xml version=""1.0"" encoding=""utf-16""?>
          <Testing xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
              <SomeProperty>true</SomeProperty>
          </Testing>",
    };

    static void Main(string[] args)
    {
        var serializer = new XmlSerializer(typeof(Testing));

        foreach (var input in s_inputs)
        {
            using (StringReader reader = new StringReader(input))
            {
                Testing instance = (Testing)serializer.Deserialize(reader);
                Console.WriteLine("Deserialized string \n{0}\n into instance with SomeProperty={1}", input, instance.SomeProperty);
            }
        }
        Console.ReadLine();
    }
}

public class Testing
{
    [DefaultValue(true)]
    public bool SomeProperty { get; set; }
}
like image 142
James Manning Avatar answered Oct 12 '22 04:10

James Manning


Regardless of how it is documented to work, I also do not see DefaultValue being assigned when deserializing. The solution for me was simply set the default value within the class constructor and give up on DefaultValueAttribute.

like image 20
James Avatar answered Oct 12 '22 05:10

James