1

I'm trying to serialize a dummy collection of orders, where each order contains a product. The collection is serializing fine, but the example product properties inside the order are being missed.

Order Collection

[XmlRoot("Orders")]
public class OrderCollection : ICollection<Order>
{
    private static List<Order> _orders;

    private List<Order> Orders
    {
        get
        {
            if(_orders == null)
            {
                _orders = new List<Order>();
            }

            return _orders;
        }
    }

    //All the ICollection functions
}

Order

public class Order
{
    [XmlElement("Id")]
    public int Id
    {
        get;
        set;
    }

    [XmlElement("Title")]
    public string Title
    {
        get;
        set;
    }

    [XmlElement("IsReserved")]
    public bool IsReserved
    {
        get;
        set;
    }

    [XmlElement("Count")]
    public int Count
    {
        get
        {
            return this.Products.Count;
        }
        set
        {

        }
    }

    // not serializing
    [XmlElement("Product")]
    public Product ProductTest
    {
        get
        {
            return new Product();
        }
    }

    // not serializing
    [XmlArray("Products")]
    public ICollection<Product> Products
    {
        get
        {
            return this._products;
        }

    }

    private List<Product> _products;

    public Order()
    {
        var rand = new Random();
        var count = rand.Next(1, 5);
        this._products = new List<Product>();

        for (int i = 0; i < count; i++)
        {
            this._products.Add(new Product());
        }
    }
}

Product

[Serializable]
public class Product 
{
    [XmlElement("Id")]
    public int Id
    {
        get;
        set;
    }

    [XmlElement("Title")]
    public string Title
    {
        get;
        set;
    }

    public Product()
    {
        var rand = new Random();
        this.Id = rand.Next(100, 9999);
        this.Title = "Product " + this.Id;
    }
}

Output

<?xml version="1.0"?>
<Orders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Order>
    <Id>619883</Id>
    <Title>Order 619883</Title>
    <IsReserved>false</IsReserved>
    <Count>3</Count>
  </Order>
  <Order>
    <Id>961448</Id>
    <Title>Order 961448</Title>
    <IsReserved>false</IsReserved>
    <Count>3</Count>
  </Order>
  <Order>
    <Id>483677</Id>
    <Title>Order 483677</Title>
    <IsReserved>false</IsReserved>
    <Count>2</Count>
  </Order>
  <Order>
    <Id>512026</Id>
    <Title>Order 512026</Title>
    <IsReserved>false</IsReserved>
    <Count>2</Count>
  </Order>
  <Order>
    <Id>916029</Id>
    <Title>Order 916029</Title>
    <IsReserved>false</IsReserved>
    <Count>4</Count>
  </Order>
  <Order>
    <Id>109800</Id>
    <Title>Order 109800</Title>
    <IsReserved>false</IsReserved>
    <Count>4</Count>
  </Order>
</Orders>

I'm completely baffled. Deep serialization seems to be working because otherwise order wouldn't get serialized inside the OrderCollection, but then it just stops. Any advice?

Nikita B
  • 3,303
  • 1
  • 23
  • 41
Craig
  • 474
  • 7
  • 21
  • I think `[XmlElement("Products")] public ICollection Products` should be `[XmlArray("Products")] public ICollection Products` http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlarrayattribute.aspx – asawyer Sep 27 '13 at 11:55
  • I already tried that, and to rule it out I added that single ProductTest property which isn't serializing either. – Craig Sep 27 '13 at 11:57
  • 1
    Try ditching all the extra code you have there. Create your classes as _simple_ plain-old-CLR-objects. No empty setters, no get-only properties, nothing fancy and see what happens. (Also, why is the backing field `private static List _orders;` static?) For your XML serialization, you're best off just having a simple data model that represents your XML schema. If you want to add business/logic/validation, do it separately by converting to/from internal business classes which don't care about serialization concerns. – Chris Sinclair Sep 27 '13 at 12:01
  • Have you applied the XmlRoot attribute to all your classes? [XmlRoot("Product")] – Ryan Gunn Sep 27 '13 at 12:02

3 Answers3

4

You have to change ICollection to List. An interface isn't serializeable.

[XmlArray("Products")]
public List<Product> Products
{
    get
    {
        return this._products;
    }

}

And ProductTest doesn't work because of the missing setter

Uwe
  • 316
  • 1
  • 7
  • Excellent, this worked. Thanks. Question though, I'm pretty sure code analysis is going to complain about having a public list rather than an ICollection - so what's best to do there? – Craig Sep 27 '13 at 12:46
  • You can use a Collection instead of a List or disable the rule. Both are valid ways (in my opinion). If you want a Collection, you can use this to create one new Collection(this._products); – Uwe Sep 27 '13 at 12:58
0

You can't serialize an interface..

An interface is nothing more than a description of a set of behaviors. It says nothing about the contents of an instance. In particular, although an instance of a class implementing an interface must implement all of its members, it will certainly have properties of its own which need to be serialized.

PS: copied from Serializing interfaces

Community
  • 1
  • 1
Pankaj
  • 2,618
  • 3
  • 25
  • 47
0

Change into List.

Public List Products {

}

Marsh
  • 173
  • 1
  • 14