使用反射将 XML 数组反序列化为列表

Deserialize an XML array into a list using reflection

提问人:Hooman Bahreini 提问时间:3/2/2021 更新时间:3/2/2021 访问量:218

问:

我想将XML文档反序列化为一个对象,这是我的对象定义:

public class Student
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public List<string> Hobbies { get; set; }
}

这是XML文件,节点名称与类属性匹配:

<?xml version="1.0" encoding="UTF-8"?>
<items>
    <item type="dict">
        <FirstName type="str">John</FirstName>
        <LastName type="str">Smith</LastName>
        <Hobbies type="list">
            <item type="str">Reading</item>
            <item type="str">Singing</item>
            <item type="str">Tennis</item>
        </Hobbies>
    </item>
</items>

以下代码曾经起作用,我会将 XML 节点(在本例中)传递给函数,代码将使用反射将属性与子节点匹配并设置属性值:item

public void DeserializeNode(XmlNode node)
{
    var student = new Student();

    foreach (XmlNode child in node)
    {
        PropertyInfo prop = student.GetType().GetProperty(child.Name);
        prop.SetValue(student, child.InnerText);
    }
}

但是上面的函数不再起作用(XML输入已更改,现在它有一个名为hobbies的数组)

以下行引发异常:

prop.SetValue(student, child.InnerText); // child.InnerText = ReadingSingingTennis

这是因为对于 Hobbies 返回,代码尝试将 tp 设置为单个 .child.InnerTextReadingSingingTennisList<string>string

如何修改此功能以正确设置爱好?

C# 反射 XML 反序列化 PropertyInfo

评论

0赞 Peter Csala 3/2/2021
它抛出什么样的异常?异常的消息是什么?

答:

1赞 Svyatoslav Ryumkin 3/2/2021 #1

问题是,在爱好中,你有节点。

所以你可以像这样尝试。

 public static void DeserializeNode(XmlNode node)
    {
        var student = new Student();

        foreach (XmlNode child in node)
        {
            PropertyInfo prop = student.GetType().GetProperty(child.Name);
            if (child.Attributes.GetNamedItem("type").Value == "list")
            {
                var list = Activator.CreateInstance(prop.PropertyType);
                foreach (XmlNode item in child)
                {
                    var methodInfo = list.GetType().GetMethod("Add");
                    methodInfo.Invoke(list, new object[] { item.InnerText });
                }

                prop.SetValue(student, list);
            }
            else
            {
                prop.SetValue(student, child.InnerText);
            }
        }
    }

但是,如果你有更复杂的 xml,你应该使用递归和反射