将XML反序列化为C#中的列表

时间:2017-01-23 15:00:44

标签: c# xml serialization

我有一组具有以下结构的类:计划>元素>列表与LT;组件>

[Serializable, XmlRoot("Plan")]
public class Plan
{
    public Plan()
    {
        elements = new Elements();
    }

    public int floor {get; set}; 

    [XmlElement("elements")]
    public Elements elements { get; set; }
}

[Serializable, XmlType("elements")]
public class Elements
{
    public Elements() { Items = new List<Element>(); }
    [XmlElement("element")]
    public List<Element> Items { get; set; }
}

[Serializable]
public class Element
{
    public int id { get; set; }
}

所有这些都使用System.Xml.Serialization序列化到这个XML:

<?xml version="1.0"?>
<Plan xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <elements>
    <element>
      <id>0</id>
    </element>
  </elements>
</Plan>

但是当我尝试再次反序列化时,Elements类根本没有填充,并且在Serialize-&gt; Deserialize-&gt; Serialize过程之后的结果如下所示:

<?xml version="1.0"?>
<Plan xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <floor>0</floor>
    <elements />
</Plan>

这是我的反序列化功能:

public class Program {
    public Plan plan;

    public static void deserializeXml<T>(this T toDeserialize, string filename)
    {
       XmlSerializer xmlSerializer = new XmlSerializer(toDeserialize.GetType());

       Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
       toDeserialize = (T) xmlSerializer.Deserialize(stream);
    }

    public void loadXml() {
        deserializeXml(plan, "plan.xml");
    }
}

有人能给我一个线索,为什么这不起作用?谢谢!

1 个答案:

答案 0 :(得分:0)

我让你的代码使用与序列化本身无关的微小修改,因此问题似乎不是xml序列化本身,而是它的调用方式:

public static void deserializeXml<T>(this T toDeserialize, string filename)
{
   // !!!! toDeserialize is a copy to instance in the heap, so -> ...

   XmlSerializer xmlSerializer = new XmlSerializer(toDeserialize.GetType());

   Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
   // -> ... here we assign reference of deserialized instance to toDeserialize(which is a copy)
   toDeserialize = (T) xmlSerializer.Deserialize(stream);

   // we need to return result here, otherwise this reference copy will be left dying here
}

代码:

static class Serializer
{
    // note here: deserializeXml returns reference to deserialized instance
    public static T deserializeXml<T>(string filename)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

        using (Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            var toDeserialize = (T)xmlSerializer.Deserialize(stream);
            return toDeserialize;
        }
    }

    public static void serializeToXml<T>(T instance, string filename)
    {
        var xmlSerializer = new XmlSerializer(instance.GetType());
        using (Stream stream = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
        {
            xmlSerializer.Serialize(stream, instance);
        }
    }
}

所以以下列方式运行它:

    Plan p = new Plan();
    p.elements.Items.Add(new Element { id = 1 });
    p.elements.Items.Add(new Element { id = 2 });
    p.elements.Items.Add(new Element { id = 3 });

    Serializer.serializeToXml(p, @"D:\1.xml");
    var p2 = Serializer.deserializeXml<Plan>(@"D:\1.xml");
    Console.WriteLine(p2.elements.Items.Count);
    Serializer.serializeToXml(p2, @"D:\2.xml");

最后会给出相同的D:\1.xmlD:\2.xml。 希望这有帮助