平展父/子层次结构

本文关键字:层次结构 | 更新日期: 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 有一个子项列表,而第一个代码适用于一个子项,但不适用于其中的许多子项。

结论:

不确定您要实现的目标,

你为什么不保持对象的结构,就像现在一样呢?