使用反射将 XML 数组反序列化为列表
Deserialize an XML array into a list using reflection
我想将一个 XML 文档反序列化为一个对象,这是我的对象定义:
public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<string> Hobbies { get; set; }
}
这是 XML 文件,节点名称匹配 class 属性:
<?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
这是因为 child.InnerText
爱好 return ReadingSingingTennis
并且代码试图将 List<string>
tp 设置为单个 string
.
如何修改此功能才能正确设置兴趣爱好?
问题是在爱好中你有节点。
所以你可以这样试试。
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你应该使用递归和反射
我想将一个 XML 文档反序列化为一个对象,这是我的对象定义:
public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<string> Hobbies { get; set; }
}
这是 XML 文件,节点名称匹配 class 属性:
<?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
这是因为 child.InnerText
爱好 return ReadingSingingTennis
并且代码试图将 List<string>
tp 设置为单个 string
.
如何修改此功能才能正确设置兴趣爱好?
问题是在爱好中你有节点。
所以你可以这样试试。
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你应该使用递归和反射