0

I am creating an app that fetches fuel prices from a web service. I want to deserialise the prices a IDictionary of Price objects with the fuel as the key (similar to this).

I had created a setter to do this but have since found out that the serialisation uses the Add method rather than the setter for lists. Is there a way of doing this using the serialisation API or will I have to write custom serialisation code?

The XML looks like this

<?xml version="1.0"?>
<prices>
    <price fuel="Petrol">152.43</price>
    <price fuel="Diesel">147.53</price>
</prices>

The code looks like this

[XmlRoot("prices")]
public class FuelPrices
{
    private IDictionary<Fuel, Price> prices = new Dictionary<Fuel, Price>();

    // This is used for serialising to XML
    [XmlElement("price")]
    public ICollection<Price> Prices
    {
        get
        {
            return prices.Values;
        }
        set
        {
            prices = new Dictionary<Fuel, Price>();
            foreach (Price price in value)
            {
                prices[price.Fuel] = price;
            }
        }
    }

    // These properties are used to access the prices in the code
    [XmlIgnore]
    public Price PetrolPrice
    {
        get
        {
            Price petrolPrice;
            prices.TryGetValue(Fuel.Petrol, out petrolPrice);
            return petrolPrice;
        }
    }

    [XmlIgnore]
    public Price DieselPrice
    {
        get
        {
            Price dieselPrice;
            prices.TryGetValue(Fuel.Diesel, out dieselPrice);
            return dieselPrice;
        }
    }
}
Community
  • 1
  • 1
robingrindrod
  • 474
  • 4
  • 18
  • What is `Price` and `Fuel`? And why you want to use deserialization instead of parsing? – Sergey Berezovskiy Jul 04 '13 at 07:36
  • Price is a class that has a price and fuel. Fuel is an enum. I didn't post the code for these to avoid cluttering the question but I can if you'd like. As for why I wanted to use serialisation, it seems to be neater and less code. Also, if I write code to parse the XML, I will have to write more code to convert it back to XML, serialisation will give me this for free. – robingrindrod Jul 04 '13 at 07:43

2 Answers2

1

You can write a wrapper around a dictionary along the lines of

sealed class DictionaryWrapper<K, T> : ICollection<T>
{
    private readonly Func<T, K> m_keyProjection ;
    private readonly IDictionary<K, T> m_dictionary ;

    // expose the wrapped dictionary
    public IDictionary<K, T> Dictionary { get { return m_dictionary ; }}

    public void Add (T value)
    {
        m_dictionary[m_keyProjection (value)] = value ;
    }

    public IEnumerator<T> GetEnumerator ()
    {
        return m_dictionary.Values.GetEnumerator () ;
    }

    // the rest is left as excercise for the reader
}

and use it like this

private DictionaryWrapper<Fuel, Price> pricesWrapper = 
    new DictionaryWrapper<Fuel, Price> (
           new Dictionary<Fuel, Price> (), price => price.Fuel) ;

[XmlElement("price")]
public ICollection<Price> Prices
{
    get { return pricesWrapper ; } // NB: no setter is necessary
}
Anton Tykhyy
  • 19,370
  • 5
  • 54
  • 56
0

if you do not want to write custom serialization - you can do this:

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;

namespace ConsoleApplication2
{
    public class Program
    {
        [XmlType("price")]
        public class Price
        {
            [XmlText]
            public double price { get; set; }

            [XmlAttribute("fuel")]
            public string fuel { get; set; }
        }

        [XmlType("prices")]
        public class PriceList : List<Price>
        {

        }

        static void Main(string[] args)
        {
            //Serialize
            var plist = new PriceList()
                {
                    new Price {price = 153.9, fuel = "Diesel"},
                    new Price {price = 120.6, fuel = "Petrol"}
                };
            var serializer = new XmlSerializer(typeof(PriceList));
            var sw = new StringWriter();
            var ns = new XmlSerializerNamespaces();
            ns.Add("", "");

            serializer.Serialize(sw, plist, ns);
            var result = sw.ToString();//result xml as we like

            //Deserialize

            var sr = new StringReader(result);
            var templist = (PriceList)serializer.Deserialize(sr);
            var myDictionary = templist.ToDictionary(item => item.fuel, item => item.price);
        }
    }
}

and if you need custom serialization - look at this post:Why isn't there an XML-serializable dictionary in .NET?

Community
  • 1
  • 1
sqladmin
  • 2,079
  • 2
  • 16
  • 11