我正在尝试将XML文档反序列化为List<>。我的目标是拥有List<>有一个公共静态方法,它返回从XML文档中填充的内容。
这是XML:
<?xml version="1.0"?>
<root>
<item>
<name>Blue</name>
</item>
<item>
<name>Red</name>
</item>
</root>
这是项目的类(BillingItem.cs):
using System;
using System.Xml.Serialization;
namespace DeserializeExample
{
[Serializable]
[XmlRoot("item")]
public class BillingItem
{
[XmlElement("name")]
public string Description { get; set; }
}
}
这是列表(BillingItems.cs)的类:
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
namespace DeserializeExample
{
[Serializable]
[XmlRoot("root")]
public class BillingItems : List<BillingItem>
{
public static BillingItems GetBillingItems()
{
using (TextReader reader = new StreamReader("BillingItems.xml"))
{
XmlSerializer serializer = new XmlSerializer(typeof(BillingItems));
return (BillingItems)serializer.Deserialize(reader);
}
}
}
}
以下是控制台应用程序,其中包含了我希望如何获取列表的示例(Program.cs):
namespace DeserializeExample
{
class Program
{
static void Main(string[] args)
{
BillingItems billingItems = BillingItems.GetBillingItems();
}
}
}
控制台应用程序运行时,列表为空。我认为这与我如何使用属性有关,但我无法确定如何使用它。
我希望这个例子很简单,解释得很好,有人可以提供帮助。
答案 0 :(得分:3)
我将封装列表 - 部分是为了简单(避免一些gnarly重载XmlSerializer
构造函数),部分原因是因为CF等上有一些故障导致它不可靠的。但是:
public class BillingItem
{
[XmlElement("name")]
public string Description { get; set; }
}
[XmlRoot("root")]
public class MyResult
{
[XmlElement("item")]
public List<BillingItem> Items { get; set; }
}
(我删除了所有不必要的其他属性)
然后你只需返回MyResult
(显然更恰当地命名),它将根据你的例子进行序列化。
答案 1 :(得分:1)
从您的示例看起来可能没有必要进行序列化。如果不是,请考虑使用LINQ-to-XML进行解析:
using System.Xml.Linq;
public class BillingItems : List<BillingItem>
{
// Constructor.
private BillingItems(List<BillingItem> items) : base(items) { }
public static BillingItems GetBillingItems()
{
var doc = XDocument.Load("BillingItems.xml");
var items = (from i in doc.Element("root").Elements("item")
select new BillingItem { Description = i.Element("name").Value })
.ToList();
return new BillingItems(items);
}
}
您可能还想考虑使用IEnumerable&lt;&gt;而不是List&lt;&gt;除非您打算插入/移除物品。
编辑:修改上面的代码,以便BillingItems根据下面的OP评论继承List&lt;&gt ;.
答案 2 :(得分:0)
好吧,虽然我不喜欢这个,因为我相信XmlSerializer中有一些东西会为我做这件事,但是在此期间我会做以下事情。
使用我真正想要的列表添加封装类:
using System.Xml.Serialization;
namespace DeserializeExample
{
[XmlRoot("root")]
public class BillingItemResult
{
[XmlElement("item")]
public BillingItems Items { get; set; }
}
}
然后在我的BillItems.cs类中,private static void方法将获取封装对象并返回它的计费项列表:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace DeserializeExample
{
[Serializable]
[XmlRoot("root")]
public class BillingItems : List<BillingItem>
{
public static BillingItems GetBillingItems()
{
using (TextReader reader = new StreamReader("BillingItems.xml"))
{
XmlSerializer serializer = new XmlSerializer(typeof(BillingItemResult));
BillingItemResult billingItemResult = (BillingItemResult)serializer.Deserialize(reader);
return billingItemResult.Items;
}
}
}
}
这允许现有应用程序的设计和约定保持不变。以下是CLI的示例:
using System.Collections.Generic;
namespace DeserializeExample
{
class Program
{
static void Main(string[] args)
{
BillingItems billingItems = BillingItems.GetBillingItems();
}
}
}
虽然这有效,但我仍然认为有一些更简单的东西不需要额外的包装类。