XML反序列化通用方法

alg*_*eat 10 .net c# generics serialization xml-deserialization

我有下一个XML文件:

<Root>
    <Document>      
        <Id>d639a54f-baca-11e1-8067-001fd09b1dfd</Id>
        <Balance>-24145</Balance>
    </Document>
    <Document>      
        <Id>e3b3b4cd-bb8e-11e1-8067-001fd09b1dfd</Id>
        <Balance>0.28</Balance> 
    </Document>
</Root>
Run Code Online (Sandbox Code Playgroud)

我把它反序列化到这个类:

[XmlRoot("Root", IsNullable = false)]
public class DocBalanceCollection
{
    [XmlElement("Document")]
    public List<DocBalanceItem> DocsBalanceItems = new List<DocBalanceItem>();
}
Run Code Online (Sandbox Code Playgroud)

在哪里DocBalanceItem:

public class DocBalanceItem
{
    [XmlElement("Id")]
    public Guid DocId { get; set; }

    [XmlElement("Balance")]
    public decimal? BalanceAmount { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这是我的反序列化方法:

public DocBalanceCollection DeserializeDocBalances(string filePath)
{
    var docBalanceCollection = new DocBalanceCollection();

    if (File.Exists(filePath))
    {
        var serializer = new XmlSerializer(docBalanceCollection.GetType());
        TextReader reader = new StreamReader(filePath);
        docBalanceCollection = (DocBalanceCollection)serializer.Deserialize(reader);
        reader.Close();
    }

    return docBalanceCollection;
}
Run Code Online (Sandbox Code Playgroud)

一切正常,但我有很多XML文件.除了编写Item类,我还必须ItemCollection为每个类编写类.而且我必须DeserializeItems为每个实现方法.

我可以在不创建ItemCollection类的情况下反序列化我的XML文件吗?我可以编写单个通用方法来反序列化所有这些吗?

想到的唯一解决方案 - 为所有这些类创建一个接口.有任何想法吗?

luk*_*san 7

您可以List<T>使用XmlSerializer 反序列化通用.但是,首先需要将XmlType属性添加到您的位置,DocBalanceItem以便知道列表元素的命名方式.

[XmlType("Document")]
public class DocBalanceItem
{
    [XmlElement("Id")]
    public Guid DocId { get; set; }

    [XmlElement("Balance")]
    public decimal? BalanceAmount { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后修改您的DeserializeDocBalances()方法以返回一个List<T>并向序列化程序传递一个XmlRootAttribute实例,以指示它Root作为根元素查找:

public List<T> DeserializeList<T>(string filePath)
{
    var itemList = new List<T>();

    if (File.Exists(filePath))
    {
        var serializer = new XmlSerializer(typeof(List<T>), new XmlRootAttribute("Root"));
        TextReader reader = new StreamReader(filePath);
        itemList = (List<T>)serializer.Deserialize(reader);
        reader.Close();
    }

    return itemList;
}
Run Code Online (Sandbox Code Playgroud)

那你应该可以做到

var list = DeserializeList<DocBalanceItem>("somefile.xml");

由于该方法现在返回泛型List<T>,因此您不再需要为每种类型创建自定义集合.

PS - 我使用提供的文档在本地测试了此解决方案,它确实有效.

  • 更新了我的答案,以便将"DeserializeDocBalances"重命名为"DeserializeList"以避免混淆. (2认同)