2013-07-04 87 views
0

我正在創建一個從Web服務獲取燃料價格的應用程序。我想用燃料作爲關鍵字對價格對象的IDictionary進行反序列化(類似於this)。將XML反序列化爲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; 
     } 
    } 
} 
+0

什麼是'Price'和'Fuel'?爲什麼你想使用反序列化而不是解析? –

+0

價格是一個有價格和燃料的類。燃料是一個枚舉。我沒有發佈這些代碼,以避免混淆這個問題,但我可以,如果你願意。至於我爲什麼要使用序列化,它似乎是整潔,少代碼。另外,如果我編寫解析XML的代碼,我將不得不編寫更多代碼將其轉換回XML,序列化將免費提供給我。 – robingrindrod

回答

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 
} 
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?