平展父/子层次结构
本文关键字:层次结构 | 更新日期: 2023-09-27 17:57:47
我试图在这里理解一个概念:
从对象结构,如
class Parent
{
public string ParentID { get; set; }
public List<Child> Children { get; set; }
}
class Child
{
public string ChildID { get; set; }
}
假设有一个完全填充的父对象,我想使用 Linq to Xml 来获取以下 Xml 输出:
<Mappings>
<Mapping ID='ParentID1' ChildID='ChildID1'>
<Mapping ID='ParentID1' ChildID='ChildID2'>
</Mappings>
如何展开嵌套的原始对象以获取此映射列表?
编辑
具有父级的示例,例如:
ParentID = 'Parent1', Children = new [] { "Child1", "Child2", "Child3" }
我期待 3 个映射:
<Mapping ID='Parent1' ChildID='Child1' />
<Mapping ID='Parent1' ChildID='Child2' />
<Mapping ID='Parent1' ChildID='Child3' />
编辑
以下代码将扁平化层次结构:
var list = new List<Parent>
{
new Parent
{
ParentID = "parentID1",
Children = new List<Child> {new Child {ChildID = "childID1"}, new Child {ChildID = "childID2"}}
},
new Parent
{
ParentID = "parentID2",
Children = new List<Child> {new Child {ChildID = "childID3"}, new Child {ChildID = "childID4"}}
}
};
IEnumerable<XElement> list1 = (from parent in list
from child in parent.Children
select
new XElement("Mapping", new XAttribute("ID", parent.ParentID),
new XAttribute("ChildID", child.ChildID)));
string @join = string.Join(Environment.NewLine, list1);
输出:
<Mapping ID="parentID1" ChildID="childID1" />
<Mapping ID="parentID1" ChildID="childID2" />
<Mapping ID="parentID2" ChildID="childID3" />
<Mapping ID="parentID2" ChildID="childID4" />
这是一个关于如何实现它的示例:
注意:这不起作用,它将生成一个异常,说"重复属性">
List<Parent> list = new List<Parent>
{
new Parent() {ParentID = "parentID1", Children = new List<Child>() {new Child() {ChildID = "childID1"},new Child() {ChildID = "childID2"}}},
new Parent() {ParentID = "parentID2", Children = new List<Child>() {new Child() {ChildID = "childID3"},new Child() {ChildID = "childID4"}}}
};
IEnumerable<string> enumerable = xElements.Select(s => s.ToString());
IEnumerable<XElement> xElements = list.Select(s => new XElement("Mapping", new XAttribute("ID", s.ParentID), s.Children.Select(t => new XAttribute("ChildID", t.ChildID))));
IEnumerable<string> enumerable = xElements.Select(s => s.ToString());
var @join = string.Join(Environment.NewLine, enumerable);
这将因为它将使用使用当前对象索引的Select
的重载:
var list = new List<Parent>
{
new Parent
{
ParentID = "parentID1",
Children = new List<Child> {new Child {ChildID = "childID1"}, new Child {ChildID = "childID2"}}
},
new Parent
{
ParentID = "parentID2",
Children = new List<Child> {new Child {ChildID = "childID3"}, new Child {ChildID = "childID4"}}
}
};
IEnumerable<XElement> xElements =
list.Select(
s =>
new XElement("Mapping", new XAttribute("ID", s.ParentID),
s.Children.Select((t, u) => new XAttribute(string.Format("ChildID_{0}", u), t.ChildID))));
var @join = string.Join(Environment.NewLine,xElements);
结果:不是你所期待的,对吧?
<Mapping ID="parentID1" ChildID_0="childID1" ChildID_1="childID2" />
<Mapping ID="parentID2" ChildID_0="childID3" ChildID_1="childID4" />
为什么我使用这个重载?
因为 parent 有一个子项列表,而第一个代码适用于一个子项,但不适用于其中的许多子项。
结论:
不确定您要实现的目标,
你为什么不保持对象的结构,就像现在一样呢?