2010-06-14 29 views
5

我想將以下XML反序列化/序列化爲一個對象。如何用xml中的C#中的多個數據類型序列化列表?

<Discounts> 
     <Discount Type="Voucher" Key="ABCD00001" Percent="2" /> 
     <Discount Type="Quantity"> 
     <Periods> 
      <Period From="Thu, 31 Dec 2009 23:00:00 GMT" Quantity="1" /> 
      <Period From="Thu, 31 Dec 2009 23:00:00 GMT" Quantity="2" /> 
     </Periods> 
     </Discount> 
    </Discounts> 

是否有可能讓@Type屬性定義應使用哪種類型的對象來序列化?

例如,在C#:

[XmlArray] 
[XmlArrayItem("Discount",typeof(Voucher)] 
[XmlArrayItem("Discount",typeof(Quantity)] 
public List<Discount> Discounts { get; set; } 

我希望我的解釋是有道理的。任何幫助,將不勝感激。謝謝。

後更新安德魯·安德森答案:

以下是更新XML:

<Discounts> 
     <Discount xsi:Type="Voucher" Key="ABCD00001" Percent="2" /> 
     <Discount xsi:Type="Quantity"> 
     <Periods> 
      <Period From="Thu, 31 Dec 2009 23:00:00 GMT" Quantity="1" /> 
      <Period From="Thu, 31 Dec 2009 23:00:00 GMT" Quantity="2" /> 
     </Periods> 
     </Discount> 
    </Discounts> 

我改變我的類看起來就像這樣:

[Serializable] 
    [XmlInclude(typeof(Voucher))] 
    [XmlInclude(typeof(Quantity))] 
    [XmlRoot("Discount")] 
    public class Discount 
    { ... } 

    public class Quantity : Discount { } 

    public class Voucher : Discount { } 

當我反序列化這個,「折扣」列表有兩個「折扣」對象。我期望在這一點上,清單應該有一個'數量'對象和'憑證'對象。這可能是因爲我的列表被定義爲只有一個「折扣」對象。以下是我的「折扣」列表對象的代碼。

[XmlArray] 
    [XmlArrayItem("Discount")] 
    public List<Discount> Discounts { get; set; } 

現在的問題是如何設置列表以包含兩種不同類型的對象?

+0

另外,你對XML的外觀靈活,或者它必須是完全按照您所貼? – 2010-06-14 15:55:48

+0

你負責格式嗎?如果是這樣,爲什麼不用XML中的「VoucherDiscount」和「QuantityDiscount」替換「Discount」? – Joseph 2010-06-14 15:59:32

+0

當它出現時,對它使用樣式表似乎是最容易的,當它出來時,但我想避免改變任何東西。 – chafnan 2010-06-14 16:51:37

回答

5

如果您可以控制XML,則可以使用Discount基類中的XmlInclude屬性來處理此問題。

例如(超前未測試的代碼):

[Serializable] 
[XmlInclude(typeof(Voucher))] 
[XmlInclude(typeof(Quantity))] 
[XmlRoot("Discount")] 
public class Discount { } 

public class Quantity : Discount { } 
public class Voucher : Discount { } 

生成的XML將看起來像這樣:

<Discounts> 
    <Discount xsi:type="Voucher" Key="ABCD00001" Percent="2" /> 
    <Discount xsi:type="Quantity"> 
    <Periods> 
     <Period From="Thu, 31 Dec 2009 23:00:00 GMT" Quantity="1" /> 
     <Period From="Thu, 31 Dec 2009 23:00:00 GMT" Quantity="2" /> 
    </Periods> 
    </Discount> 
</Discounts> 

UPDATE

這裏是類的樣本集與一個控制檯應用程序來演示從這種格式的序列化& deserialing。

首先,數據定義:

[Serializable] 
public class Shopping 
{ 
    [XmlArray] 
    [XmlArrayItem("Discount")] 
    public List<Discount> Discounts { get; set; } 
} 

[Serializable] 
[XmlInclude(typeof(Voucher))] 
[XmlInclude(typeof(Quantity))] 
[XmlRoot("Discount")] 
public class Discount 
{ 
    public int Amount { get; set; } 
} 

public class Quantity : Discount 
{ 
    public int MyQuantity { get; set; } 
} 

public class Voucher : Discount 
{ 
    public string MyVoucherName { get; set; } 
} 

與測試程序:

public class Program 
{ 
    static void Main(string[] args) 
    { 
     XmlSerializer xs = new XmlSerializer(typeof(Shopping)); 

     var myShopping = new Shopping(); 
     myShopping.Discounts = new List<Discount>(); 
     myShopping.Discounts.Add(new Voucher() {MyVoucherName = "Foo", Amount = 6}); 
     myShopping.Discounts.Add(new Quantity() { MyQuantity = 100, Amount = 6 }); 

     StringBuilder xml = new StringBuilder(); 
     XmlWriter xmlWriter = XmlWriter.Create(xml); 

     xs.Serialize(xmlWriter, myShopping); 

     Console.WriteLine("Serialized:"); 
     Console.WriteLine(xml); 

     Console.WriteLine(); 
     Console.WriteLine("Deserialized:"); 

     TextReader tr = new StringReader(xml.ToString()); 
     var myNewShopping = (Shopping) xs.Deserialize(tr); 

     if (myNewShopping.Discounts != null) 
     { 
      foreach (var discount in myNewShopping.Discounts) 
      { 
       if (discount is Voucher) 
       { 
        var voucher = (Voucher) discount; 
        Console.WriteLine("Voucher - Amount={0}, Name={1}", voucher.Amount, voucher.MyVoucherName); 
       } 
       else if (discount is Quantity) 
       { 
        var quantity = (Quantity)discount; 
        Console.WriteLine("Quantity - Amount={0}, #={1}", quantity.Amount, quantity.MyQuantity); 
       } 
       else 
       { 
        Console.WriteLine("Discount - Amount={0}", discount.Amount); 
       } 
      } 
     } 
     else 
     { 
      Console.WriteLine("No Discounts found"); 
     } 

     Console.ReadKey(); 
    } 
+0

我在我的樣本中有一堂課。在您的帖子中,您可以裝飾折扣列表 - 除[XmlArray]之外,您不需要任何其他屬性。 – 2010-06-14 17:00:23

+0

工作。現在的問題是,現在列表中的類型對象是「折扣」,因爲我希望它是加載的對象的類型,例如「數量」或「憑證」。無論如何讓加載的對象在列表中是正確的? – chafnan 2010-06-14 17:02:25

+0

對不起,我刪除了我的第一條評論,因爲我讀了你的回答錯誤,並在錯誤的地方應用了XmlInclude。 – chafnan 2010-06-14 17:03:11

相關問題