【问题标题】:XML deserialization generic methodXML反序列化泛型方法
【发布时间】:2014-09-28 23:38:56
【问题描述】:

我有下一个 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>

我将它反序列化为这个类:

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

DocBalanceItem 在哪里:

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

    [XmlElement("Balance")]
    public decimal? BalanceAmount { get; set; }
}

这是我的反序列化方法:

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;
}

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

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

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

【问题讨论】:

  • 您尝试过使用dynamic 吗?
  • 我不确定它会起作用。无论如何,我需要指定 [XmlRoot("Root", IsNullable = false)] 和 [XmlElement("Document")] somewere。你能提供一些代码吗?

标签: c# .net generics serialization xml-deserialization


【解决方案1】:

您可以使用 XmlSerializer 反序列化通用 List&lt;T&gt;。但是,首先您需要将 XmlType 属性添加到您的 DocBalanceItem 以便它知道列表元素的命名方式。

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

    [XmlElement("Balance")]
    public decimal? BalanceAmount { get; set; }
}

然后修改您的 DeserializeDocBalances() 方法以返回一个 List&lt;T&gt; 并向序列化程序传递一个 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;
}

那你应该可以了

var list = DeserializeList&lt;DocBalanceItem&gt;("somefile.xml");

由于该方法现在返回一个通用的List&lt;T&gt;,您不再需要为每种类型创建自定义集合。

附: - 我用提供的文档在本地测试了这个解决方案,它确实有效。

【讨论】:

  • 更新了我的答案,将DeserializeDocBalances 重命名为DeserializeList 以避免混淆。
  • 谢谢。我稍后会测试它
【解决方案2】:

任何可字符串化的对象都可以通过以下方法反序列化。

public static T genericDeserializeSingleObjFromXML<T>(T value, string XmalfileStorageFullPath)
        {             
            T Tvalue = default(T);
            try
            {
                XmlSerializer deserializer = new XmlSerializer(typeof(T));
                TextReader textReader = new StreamReader(XmalfileStorageFullPath);
                Tvalue = (T)deserializer.Deserialize(textReader);
                textReader.Close();

            }
            catch (Exception ex)
            {                   
            System.Windows.Forms.MessageBox.Show("serialization Error : " + ex.Message);                
            }
            return Tvalue;
        }

为了使用这个方法,你应该已经序列化了 xml 文件中的对象。 调用方法是:

XmlSerialization.genericDeserializeSingleObjFromXML(new ObjectName(), "full path of the XML file");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多