将XML废弃为IDictionary

本文关键字:IDictionary 废弃 XML | 更新日期: 2023-09-27 18:20:53

我正在创建一个从web服务获取燃油价格的应用程序。我想取消价格的分类,这是以燃料为关键的价格对象的IDictionary(类似于此)。

我创建了一个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;
        }
    }
}

将XML废弃为IDictionary

您可以按照的方式围绕字典编写包装器

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
}

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

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

如果你需要自定义序列化-看看这篇文章:为什么不是';.NET中没有可序列化的XML字典吗?