5

I'm looking for hints, ideas on how to implement and/or change class serialization behavior of following classes in general.

Simplified (incomplete) sample classes :

[Serializable]
public class Choobakka
{
    public string Name { get; set; }
    public VariableList<Item> Stuff { get; set; }
}
[Serializable]
public class Item
{
    public string Name { get; set; }
    public string Value { get; set; }
}
[Serializable]
public sealed class VariableList<T> : AVariableList<T>
{
    public new ItemList<T> Items { get { return _items; } set { _items = value; } }
    public new bool IsNull { get { return Items == null; } }
    public new bool IsEmpty { get { return IsNull || Count <= 0; } }
    public new int Count { get { return IsNull ? 0 : this.Items.Count; } }
    public new string CountAsString { get { return Count.ToString(); } }
    public VariableList()
    {
        _items = new ItemList<T>();
    }
}

And this is how I fill-in and serialize Choobakka's stuff

var choobakka = new Choobakka() { Name = "CHOO-BAKKA", Stuff = new VariableList<Item>()  };            
choobakka.Stuff.Items.Add( new Item() { Name = "passport", Value = "lv" } );
choobakka.Stuff.Items.Add( new Item() { Name = "wallet", Value = "50euro" } );
StringBuilder sb = new StringBuilder();
using (TextWriter tw = new StringWriter(sb))
{
    XmlSerializer xs = new XmlSerializer(typeof(Choobakka));
    xs.Serialize(tw, choobakka);
}

Serialized XML looks like:

<Choobakka>
    <Name>CHOO-BAKKA</Name>
    <Stuff>
        <Items>
            <Item>
                <Name>passport</Name>
                <Value>lv</Value>
            </Item>
            <Item>
                <Name>wallet</Name>
                <Value>50euro</Value>
            </Item>
        </Items>
    </Stuff>
</Choobakka>

Now the question is how would you suggest to get rig of <Items> tag (if possible) to something like

<Choobakka>
    <Name>CHOO-BAKKA</Name>
    <Stuff>
        <Item>
            <Name>passport</Name>
            <Value>lv</Value>
        </Item>
        <Item>
            <Name>wallet</Name>
            <Value>50euro</Value>
        </Item>
    </Stuff>
</Choobakka>

Having said that I cannot change the structure of VariableList<T> class, except applying some XML serialization attributes.

The reason for this is not just simplifying the resulting XML, but also desearializing XML generated by SQL Server queries. I have thoughts of attributes, xsd/xslt transformations...

3
  • With XmlSerializer only you don't need to use [Serializable] attribute. Commented Apr 28, 2015 at 10:15
  • Not sure how you'd do this using the built in XmlSerializer given it just walks the structure, is there any reason you couldn't do some XML manipulation prior to saving / sending the serialised data? Commented Apr 28, 2015 at 10:20
  • I wasn't quite sure about [Serializable]. Since it may bring additional security issues and in general works without one, attribute is now removed. As for the pre-saving manipulation I hoped there might be a lazier way of doing that without much code. For now I'll use a combination of @Sinatr and @jdweng answers. Somehow I've been close to these answers, but as always some tiny bit missing. Thank you! Commented Apr 28, 2015 at 12:42

3 Answers 3

1

If you can't change VariableList<>, then changing Choobaka will do

public class Choobakka
{
    public string Name { get; set; }
    [XmlIgnore]
    public VariableList<Item> Stuff { get; set; } // we do not serialize this
    [XmlArray("Stuff")]
    public Item[] _Stuff // but this
    {
        get
        {
            // get Item[] from Stuff property somehow
            // ...

            // as test
            return new Item[] {new Item() { Name = "1", Value = "111"}, new Item() { Name = "2", Value = "222"}};
        }
        set
        {
            // set Stuff property from Item[] somehow
            // ...
        }
    }
}

produces (proof)

<?xml version="1.0" encoding="utf-16"?>
<Choobakka xmlns:xsd="http://www.w3.org/2001/XMLSchema"             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Name>CHOO-BAKKA</Name>
  <Stuff>
    <Item>
      <Name>1</Name>
      <Value>111</Value>
    </Item>
    <Item>
      <Name>2</Name>
      <Value>222</Value>
    </Item>
  </Stuff>
</Choobakka>
Sign up to request clarification or add additional context in comments.

Comments

0

Just add XmlElement to the class

public sealed class VariableList<T> : AVariableList<T>
    {
        [XmlElement("Item")]
        public new ItemList<T> Items { get { return _items; } set { _items = value; } }
        public new bool IsNull { get { return Items == null; } }
        public new bool IsEmpty { get { return IsNull || Count <= 0; } }
        public new int Count { get { return IsNull ? 0 : this.Items.Count; } }
        public new string CountAsString { get { return Count.ToString(); } }
        public VariableList()
        {
            _items = new ItemList<T>();
        }
    }

1 Comment

This example works fine. I've got {"Member 'VariableListOfItem.Items' hides inherited member 'AVariableListOfItem.Items', but has different custom attributes."} error, but I had to put [XmlIgnore] attribute on the same collection in the abstract class.
0

Attribute help.

[Serializable]
public class Choobakka
{
    public string Name { get; set; }
    [XmlElement("ElementName")]
    public VariableList<Item> Stuff { get; set; }
}

output:

<Choobakka>
        <Name>CHOO-BAKKA</Name>            
        <ElementName>
            <Name>passport</Name>
            <Value>lv</Value>
        </ElementName>
        <ElementName>
            <Name>wallet</Name>
            <Value>50euro</Value>
        </ElementName>
    </Choobakka>

Further reading

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.