我希望能够从流式传输XML文档的代码返回强类型对象而不是XElements。说有问题的XML文档是:
<?xml version="1.0" encoding="utf-8" ?>
<People>
<Person>
<FirstName>John</FirstName>
<LastName>Smith</LastName>
</Person>
<Person>
<FirstName>Adam</FirstName>
<LastName>Smith</LastName>
</Person>
<Person>
<FirstName>Jane</FirstName>
<LastName>Smith</LastName>
</Person>
</People>
目前,我的读者代码如下所示:
public class PeopleReader
{
public static IEnumerable<XElement> StreamPerson(string path)
{
using (XmlReader rdr = XmlReader.Create(path))
{
rdr.MoveToContent();
while (rdr.Read())
{
if (rdr.NodeType == XmlNodeType.Element && rdr.Name == "Person")
{
XElement item = XElement.ReadFrom(rdr) as XElement;
if (item != null)
yield return item;
}
}
}
}
}
当前的调用代码是:
// Current implementation
foreach (var person in PeopleReader.StreamPerson(@"...\People.xml"))
{
MessageBox.Show(person.Element("LastName").Value);
}
我必须致电.Element
和.Value
。
我希望调用代码的是:
// Required implementation where person is returned as a strongly typed obj.
foreach (var person in PeopleReader.StreamPerson(@"...\People.xml"))
{
MessageBox.Show(person.LastName);
}
据我所知,我可以使用xsd.exe生成.XSD文件,然后生成.cs文件,但我不清楚实际步骤。另外,我不确定如何更改我的阅读器代码以返回生成的类,以便调用代码接收强类型对象进行枚举?也就是说,我如何从XElements转到强类型类 - Casting似乎不是一个选项?
我正在使用VS2015,如果可能的话,更愿意不必使用第三方工具。
非常感谢提前。
答案 0 :(得分:1)
而不是返回IEnumerable<XElement>
创建类型Person
并返回IEnumerable<Person>
:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
然后返回一个新实例:
public static IEnumerable<XElement> StreamPerson(string path)
{
using (XmlReader rdr = XmlReader.Create(path))
{
rdr.MoveToContent();
while (rdr.Read())
{
XElement item = XElement.ReadFrom(rdr) as XElement;
if (item != null)
{
yield return new Person
{
FirstName = item.Element("FirstName")?.Value,
LastName = item.Element("LastName")?.Value
};
}
}
}
}
更新 - 在了解到这些xml代表较大类的“轻量级”版本之后,我建议将这些类的源代码引用到当前项目中:
为包含轻量级属性的较大类创建基类。这样你就没有代码重复,可以从一个代码转换为另一个代码。
public class PersonBase
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Person : PersonBase
{
public string OtherProperty { get; set; }
}
然后使用我上面的方法或Charles
建议的方法来实例化对象答案 1 :(得分:1)
我建议您使用XmlSerializer
。
var serializer = new XmlSerializer(typeof(Person));
using (var rdr = XmlReader.Create(path))
{
rdr.MoveToContent();
while (rdr.Read())
{
if (rdr.NodeType == XmlNodeType.Element && rdr.Name == "Person")
{
yield return (Person) serializer.Deserialize(rdr);
}
}
}
您的课程定义如下:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
有关正常工作的演示,请参阅this fiddle。
要为XML生成类,可以使用xsd.exe
(对于XML或XML Schema,如果有的话),或者可以使用{将XML样本复制并粘贴到Visual Studio中{1}}。请参阅this related question。