【问题标题】:Deserializing Generic List<T> From XML Without XmlAttributes从没有 XmlAttributes 的 XML 反序列化通用 List<T>
【发布时间】:2018-01-06 05:08:15
【问题描述】:

我正在尝试将 xml 列表反序列化为 C# 中的通用列表。我不想使用 XmlAttributes,因为解决方案需要是通用的。我必须接近,因为我得到 3 个 Item 对象,但它们都填充了默认值,即:null 或 0。

这不是 how to deserialize an xml node with a value and an attribute using asp.net serialization 的副本,它使用 XmlAttributes 并且不是一个选项。问题中明确说明了这一点。

那里有许多我尝试过的 SO 答案,并且与我需要的类似,包括 [重复] 中的其他 SO 响应列表。下面的代码是根据其中一个答案修改的,但不太有效。

<?xml version="1.0" encoding="utf-8"?>
<root>
---snip---
    <Items>
    <Item ItemId="1" ItemName="TestName1" Number="100" Created=""></Item>
    <Item ItemId="2" ItemName="TestName2" Number="200" Created=""></Item>
    <Item ItemId="3" ItemName="TestName3" Number="300" Created=""></Item>
    </Items>
</root>

========================================================

var sourceData = XDocument.Parse(xml); 

public List<T> GetObjectList<T>(string identifier) where T : class, new()
{
    if (sourceData != null && !identifier.isNullOrEmpty())
    {
        var list = sourceData.Descendants(identifier)
            .Select(p => DeserializeObject<T>(p.ToString()))
            .ToList();

        return list;
    }
    return new List<T>();
}

public static T DeserializeObject<T>(string xml)  where T : class, new()
{
    if (string.IsNullOrEmpty(xml))
    {
        return default(T);
    }
    try
    {
        using (var stringReader = new StringReader(xml))
        {
            var serializer = new XmlSerializer(typeof(T));
            return (T) serializer.Deserialize(stringReader);
        }
    }
    catch 
    {
        return default(T);
    }
}

public class Item
{
    public int ItemId { get; set; }
    public string ItemName { get; set; }
    public int? Number { get; set;}
    public DateTime? Created { get; set; }
}

// RESULT
// Item ItemId="0" ItemName="null" Number="null" Created="null" 
// Item ItemId="0" ItemName="null" Number="null" Created="null"
// Item ItemId="0" ItemName="null" Number="null" Created="null"

【问题讨论】:

  • 这不是任何这些问题的重复,我查看了许多答案但没有找到解决方案。我可以使用 XmlAttributes 并删除 Created 字段以使上述示例正常工作,但我需要它比这更好。
  • 如果您无法修改您的Item 类型以添加​​[XmlAttribute] 属性,您可以预处理您的XML 以将所有属性转换为元素,如C# to convert xml attributes to elements 所示。顺便说一句,由于您已经将 XML 加载到 XDocument 中,因此您可以直接从 XElement 反序列化,而无需使用来自 C#: Best way to have XML element name from generic type nameXObjectExtensions.Deserialize&lt;T&gt;() 转换回字符串。
  • 默认值可能由return default(T); 创建——尤其是第二个,只是让所有异常消失而不记录它们? (尤其是“缺少属性”-例外。)

标签: c# linq deserialization linq-to-xml


【解决方案1】:

查看 XmlSerialzer 构造函数,如果你不想修改类,你可以在那里指定属性覆盖——你需要一些数据来定义你在某个时候序列化的内容;如果没有这些属性或已知可序列化的类型(数字、字符串等),XmlSerializer 永远不会被编写为工作。

如果您想要通用,则必须编写自己的序列化程序,它使用反射来决定序列化的内容、序列化的方式、顺序以及忽略的内容。在序列化具有必要属性的类型时,可以使用其中的 XmlSerializer。搜索解释如何实现 IXmlSerializable 的教程,他们将向您展示如何使用 XmlWriter / XmlReader 来避免自己处理 XML 语法。

猜测为什么会这样:循环引用使(反)序列化非常困难,通用解决方案可能会尝试序列化而不结束,从而导致奇怪的错误与调用永远挂起,当一些开发人员更改其中一个类,但无法看到(由于不存在属性)他们必须以一种避免序列化问题的方式编写类。

【讨论】:

  • 我有点晚了,但感谢您的解释。这几乎回答了这个问题,也是我当时所期待的。
【解决方案2】:

我问了另一个类似的问题 (A Better XElement to Object Without XMLAttributes in C#),当这个问题被标记为重复时(一段时间)并最终创建了一个简单的自定义反序列化器来满足我的需求。如果有兴趣,请查看那里的代码答案。

【讨论】:

    猜你喜欢
    • 2018-10-30
    • 2011-09-28
    • 2020-10-16
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 1970-01-01
    相关资源
    最近更新 更多