Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specify a different default values for XmlElement other than the one in its constructor?

Tags:

c#

xml

I have these 2 classes

[XmlType]
public class Child
{
    public Child()
    {
        X = false;
        Y = -100;
    }

    [XmlAttribute]
    public bool X { get; set; }

    [XmlAttribute]
    public int Y { get; set; }
}

[XmlRoot]
public class Parent
{
    public Parent()
    {
        C = new Child()
        {
            X = true;
        }
        ;
    }

    [XmlElement]
    public child C { get; set; }
}

when I try to parse a parent with child object that does not specify a value of x, I need x to be true not false. Example:

string xmlText = "<Parent><C y='1000'/></Parent>";
Parent p;
using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlText)))
{
    using (var reader = XmlDictionaryReader.CreateTextReader(memoryStream, Encoding.UTF8, XmlDictionaryReaderQuotas.Max, null))
    {
        var xmlDeserializer = new XmlSerializer(typeof(parent));
        p = xmlDeserializer.Deserialize(reader) as Parent;
    }
}
if(p.C.X) 
{
    Console.WriteLine("p.C.X is true");.
}
else
{
    Console.WriteLine("p.C.X is false");
}

Then if we print p.C.X it will be false not true. How to solve this problem?

Note: I have updated the question, X was int in the beginning and then I changed it be bool (that's why the answers will refer to X as an int not a bool).

like image 518
Ghooo Avatar asked Nov 19 '25 01:11

Ghooo


1 Answers

If there is no "invalid value", one solution I see is to use a boolean flag in the child class to indicate whether the X property was set or not. This flag starts as true, but then is set to false in the X setter. Then in the parent's C setter, you need to check that flag.

[XmlType]
public class Child
{
    private int x;

    public Child()
    {
        x = 10;
        UsingDefaulXValue = true;
        Y = -100;
    }

    [XmlAttribute]
    public int X
    {
        get
        {
            return x;
        }
        set
        {
            x = value;
            UsingDefaulXValue = false;
        }
    }

    [XmlIgnore]
    public bool UsingDefaulXValue { get; private set; }

    [XmlAttribute]
    public int Y { get; set; }
}

[XmlRoot]
public class Parent
{
    private const int DefaultX = 5;
    private Child c;

    public Parent()
    {
        // Careful to use property and not field
        C = new Child();
    }

    [XmlElement]
    public Child C
    {
        get
        {
            return c;
        }
        set
        {
            c = value;
            if (c.UsingDefaulXValue)
            {
                c.X = DefaultX;
            }
        }
    }
}

Trying it out:

void Main()
{
    // Checking the child's default value
    Child c1 = Deserialize<Child>("<Child/>");
    Console.WriteLine(c1.X); // it will print 10.

    Child c2 = Deserialize<Child>("<Child X='30'/>");
    Console.WriteLine(c2.X); // it will print 30.

    // Checking the parent's default value
    Parent p1 = Deserialize<Parent>("<Parent></Parent>");
    Console.WriteLine(p1.C.X); // it will print 5.

    Parent p2 = Deserialize<Parent>("<Parent><C Y='1000'/></Parent>");
    Console.WriteLine(p2.C.X); // it will print 5.

    Parent p3 = Deserialize<Parent>("<Parent><C X='20' Y='1000'/></Parent>");
    Console.WriteLine(p3.C.X); // it will print 20.
}

T Deserialize<T>(string xmlText)
{
    using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlText)))
    {
        using (var reader = XmlDictionaryReader.CreateTextReader(memoryStream, Encoding.UTF8, XmlDictionaryReaderQuotas.Max, null))
        {
            var xmlDeserializer = new XmlSerializer(typeof(T));
            return (T)xmlDeserializer.Deserialize(reader);
        }
    }
}
like image 188
vyrp Avatar answered Nov 20 '25 16:11

vyrp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!