是否可以使用LINQ to XML创建多态类型的数组?
我有3个类,Base,Der1和Der2。 Base是Der1和Der2的基类。我有一个xml文件,其中我有与Der1和Der2 objets对应的节点。我想要做的是解析文件并用Der1和Der2对象填充List。
xml看起来像这样:
<nodes>
<node type = "Der1" attr1="val1" />
<node type = "Der2" attr2="val2" />
</nodes>
我试图做但不起作用的是:
List<Base> PMList =
(from der1node from xmlDoc.Descendants("nodes")
where der1node.type == ("Der1")
select new Der1()
{
Attr1 = der1node.Attribute("attr1").Value
}
).Union<Base>
(from der2node from xmlDoc.Descendants("baseNode")
where der2node.type == ("Der2")
select new Der2()
{
Attr2 = der2node.Attribute("attr2").Value
}
).ToList<Base>();
这里我尝试做的是构造类型为= Der1的Der1对象和类型为Der2的Der2对象,并使用Union将它们一起添加到List中。
然而,这不起作用。如何使用LINQ to XML获取不同类型的对象并将它们放在一个多态集合中?
答案 0 :(得分:2)
一种方法是在投影之前将新实例强制转换为基类:
List<Base> PMList = (from baseNode from xmlDoc.Descendants("nodes")
where baseNode.type == ("Der1")
select (Base) new Der1() {
Attr1 = baseNode.Attribute("attr1").Value
}
).Union(
from baseNode from xmlDoc.Descendants("baseNode")
where baseNode.type == ("Der2")
select (Base) new Der2() {
Attr2 = baseNode.Attribute("attr2").Value
}
).ToList();
答案 1 :(得分:2)
将对象表单select选择为Base类型:
(from der1node from xmlDoc.Descendants("nodes")
where der1node.type == ("Der1")
select new Der1()
{
Attr1 = der1node.Attribute("attr1").Value
} as Base
)
答案 2 :(得分:2)
创建序列时,只需确保将投影投射到基本类型,使其成为IEnumerable<Base>
而不是IEnumerable<Der1>
。
List<Base> PMList =
(from der1node from xmlDoc.Descendants("nodes")
where der1node.type == ("Der1")
select new Der1()
{
Attr1 = der1node.Attribute("attr1").Value
} as Base).Union(
(from der2node from xmlDoc.Descendants("baseNode")
where der2node.type == ("Der2")
select new Der2()
{
Attr2 = der2node.Attribute("attr2").Value
} as Base)).ToList();
或者,您可以事先调用序列上的Cast<Base>()
。
List<Base> PMList =
(from der1node from xmlDoc.Descendants("nodes")
where der1node.type == ("Der1")
select new Der1()
{
Attr1 = der1node.Attribute("attr1").Value
}).Cast<Base>().Union(
(from der2node from xmlDoc.Descendants("baseNode")
where der2node.type == ("Der2")
select new Der2()
{
Attr2 = der2node.Attribute("attr2").Value
}).Cast<Base>()).ToList();
答案 3 :(得分:1)
另一方面,您是否考虑使用Concat代替联盟?联盟将删除重复项,在您当前的状态不应该是问题
但是,如果在某些时候您覆盖Der1
和Der2
的相等性,某些项可能会突然停止出现在列表中。很高兴意识到这一点。
无论如何,我会这样做:
var items = xmlDoc.Descendants("nodes")
.Where(d1 => d1.type == ("Der1"))
.Cast<Base>()
.Concat(xmlDoc.Descendants("nodes")
.Where(d2 => d2.type = ("Der2"))
.Cast<Base>()
).ToList();
答案 4 :(得分:0)
我知道这大约是7年后。但是,如果元素的顺序与您的用例相关。在这里,我提供了一种不使用PendingIntent
来保留订单的方法。以下代码假定“节点”是根元素。
Union