2010-08-28 77 views
5

这是我的第一个关于堆栈溢出的问题。如果在我学习这里的工作方式时我没有把事情做得很对,我会提前道歉。C#XML序列化程序不会存储属性

这里是我的代码:

public void TestSerialize() 
{ 
    ShoppingBag _shoppingBag = new ShoppingBag(); 
    Fruits _fruits = new Fruits(); 
    _fruits.testAttribute = "foo"; 

    Fruit[] fruit = new Fruit[2]; 
    fruit[0] = new Fruit("pineapple"); 
    fruit[1]= new Fruit("kiwi"); 

    _fruits.AddRange(fruit); 

    _shoppingBag.Items = _fruits; 

    Serialize<ShoppingBag>(_shoppingBag, @"C:\temp\shopping.xml"); 
} 

public static void Serialize<T>(T objectToSerialize, string filePath) where T : class 
{ 
    XmlSerializer serializer = new XmlSerializer(typeof(T)); 

    using (StreamWriter writer = new StreamWriter(filePath)) 
    { 
     serializer.Serialize(writer, objectToSerialize); 
    } 
} 

[Serializable] 
public class ShoppingBag 
{ 
    private Fruits _items; 

    public Fruits Items 
    { 
     get { return _items; } 
     set {_items = value; } 
    } 
} 

public class Fruits : List<Fruit> 
{ 
    public string testAttribute { get; set; } 
} 

[Serializable] 
public class Fruit 
{ 
    public Fruit() { } 

    public Fruit(string value) 
    { 
     Name = value; 
    } 

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

它生产这个XML:

<?xml version="1.0" encoding="utf-8" ?> 
<ShoppingBag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Items> 
    <Fruit name="pineapple" /> 
    <Fruit name="kiwi" /> 
    </Items> 
</ShoppingBag> 

我不明白为什么我没有得到<Items testAttribute="foo">

请谁能告诉我是什么需要添加到我的代码,以便序列化程序将这个属性写出来?

感谢,

+3

@ martin-65,欢迎来到SO。这是一个很好的问题,应该成为如何向本网站上更多老用户提问的例子。您已经正确格式化了您的代码,提供了一个完整的工作示例(在任何PC上很容易重现)隔离问题,提供片段的输出并解释了期望的结果。 – 2010-08-28 19:13:32

+0

感谢您的欢迎和鼓励。 – MartinC 2010-08-28 20:40:55

回答

0

不幸的是,当序列化一个集合时,XmlSerializer没有考虑到该集合的额外属性。它只考虑执行ICollection<T>的成员。如果你想序列化额外的属性,你需要将集合包装在另一个不是集合本身的类中。

2

你需要一个中介类有:

class Program 
{ 
    static void Main() 
    { 
     var shoppingBag = new ShoppingBag 
     { 
      Items = new ShoppingBagItems 
      { 
       Fruits = new List<Fruit>(new[] { 
        new Fruit { Name = "pineapple" }, 
        new Fruit { Name = "kiwi" }, 
       }), 
       TestAttribute = "foo" 
      } 
     }; 
     var serializer = new XmlSerializer(typeof(ShoppingBag)); 
     serializer.Serialize(Console.Out, shoppingBag); 
    } 
} 

public class ShoppingBag 
{ 
    public ShoppingBagItems Items { get; set; } 
} 

public class ShoppingBagItems 
{ 
    [XmlElement("Fruit")] 
    public List<Fruit> Fruits { get; set; } 

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

public class Fruit 
{ 
    [XmlAttribute("name")] 
    public string Name { get; set; } 
} 

还要注意的是,你不需要用[Serializable]属性来装饰你的类,因为它仅用于二进制序列化。另一种说法是,你不需要从List<T>派生出来,只需使用它作为属性。

+0

谢谢你的回答,Darin。 我不明白你说我需要中介班时你的意思。您已经像我一样使用了3类(ShoppingBag,ShoppingBagItems,Fruit)(ShoppingBag,Fruits,Fruit)。 感谢您提示不需要'[Serializable]'属性。 关于'List '的观点是我的问题的症结所在。如果我更改我的原始代码,以免从'List '派生'Fruits',那么它工作正常... – MartinC 2010-08-28 20:37:14

+0

但是,回到工作中,我被要求从列表派生,以便当我反序列化XML I可以很容易地在我的类上使用foreach(无需自己实现IEnumerable)。 (我的XML有7个级别的对象;我没有执行序列化,只是反序列化。开始是因为我无法读取第4级的属性,所以我想如果我可以正确序列化它,那么我应该能够反序列化它)。 那么,为什么从'List '派生'停止正在写入的属性?我怎样才能从列表派生和写/读该属性? – MartinC 2010-08-28 20:37:56