将XML反序列化为字典

时间:2013-07-04 06:29:56

标签: c# xml xml-serialization

我正在创建一个从网络服务获取燃油价格的应用程序。我想以价格对象的IDictionary反序列化,以燃料为关键字(类似于this)。

我创建了一个setter来执行此操作,但后来发现序列化使用Add方法而不是列表的setter。有没有办法使用序列化API执行此操作,还是必须编写自定义序列化代码?

XML看起来像这样

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

代码看起来像这样

[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;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

你可以沿着

的方式在字典周围写一个包装器
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
}

并像这样使用

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
}

答案 1 :(得分:0)

如果您不想编写自定义序列化 - 您可以这样做:

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);
        }
    }
}

如果您需要自定义序列化,请查看以下帖子:Why isn't there an XML-serializable dictionary in .NET?