使用LINQ的父/子Xml到DTO对象模型

时间:2013-08-28 21:24:18

标签: c# linq linq-to-xml linq-to-objects

鉴于以下DTO定义:

[Serializable]
internal class OrderCollection : List<Order>
{ }

[Serializable]
internal class Order
{
    public string OrderId { get; set; }
    public OrderDetailCollection OrderDetails { get; set; }
}


[Serializable]
internal class OrderDetailCollection : List<OrderDetail>
{ }

[Serializable]
internal class OrderDetail
{
    internal OrderDetail()
    {
    }

    /*public string ParentOrderId { get; set; }*/
    public string ItemName { get; set; }
    public int Quantity { get; set; }
}

以及以下xml:

<root>
    <orders>

        <order orderId="ABC123">
            <orderDetails>

                <orderDetail itemName="Bike" quantity="1"/>
                <orderDetail itemName="TeddyBear" quantity="2"/>
                <orderDetail itemName="Doll" quantity="3"/>

            </orderDetails>
        </order>
        <!--  -->
        <order orderId="DEF234">
            <orderDetails>

                <orderDetail itemName="Truck" quantity="4"/>
                <orderDetail itemName="Marbles" quantity="5"/>
                <orderDetail itemName="BoardGame" quantity="6"/>

            </orderDetails>
        </order>

    </orders>
</root>

有没有办法填充整个对象模型(使用Linq生成一个OrderCollection类型的对象.....并且在&#34;一次通过&#34;?

这就是我所拥有的........(我可以获得&#34; Order(s)&#34;填充)......但不确定如何让孩子们?或者我必须接受2次传球,然后“#34;匹配它们”#34; ?

    XDocument xDoc = XDocument.Load(fullFileName);

    //XNamespace ns = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");
    string ns = string.Empty;

    List<Order> lineItems = new List<Order>
    (
            from list in xDoc.Descendants(ns + "orders")
            from item in list.Elements(ns + "order")
            where item != null
            select new Order
            {
                OrderId = item.Attribute("orderId") == null ? string.Empty : item.Attribute("orderId").Value
            }
       );


    OrderCollection returnCollection = new OrderCollection();
                returnCollection.AddRange(lineItems);

1 个答案:

答案 0 :(得分:1)

试试这个:

internal class OrderDetailCollection : List<OrderDetail>
{
    internal OrderDetailCollection() {}
    internal OrderDetailCollection(IEnumerable<OrderDetail> src)
    {
        AddRange(src);
    }
}

List<Order> lineItems = new List<Order>
(
    from list in xDoc.Descendants(ns + "orders")
    from item in list.Elements(ns + "order")
    where item != null
    select new Order
    {
        //note that the cast is simpler to write than the null check in your code
        //http://msdn.microsoft.com/en-us/library/bb387049.aspx
        OrderId = (string)item.Attribute("orderId"),
        OrderDetails = new OrderDetailCollection(
            from detail in item.Descendants("orderDetail")
            select new OrderDetail {
                ItemName = (string)detail.Attribute("itemName"),
                Quantity = (int)detail.Attribute("quantity")
            }
        )
     }
);

如果您不需要单独的集合类,并且可以使用List<Order>List<OrderDetails>,那么您可以执行此操作:

List<Order> lineItems = new List<Order>
(
    from list in xDoc.Descendants(ns + "orders")
    from item in list.Elements(ns + "order")
    where item != null
    select new Order
    {
        OrderId = (string)item.Attribute("orderId"),
        OrderDetails = (
            from detail in item.Descendants("orderDetail")
            select new OrderDetail {
                ItemName = (string)detail.Attribute("itemName"),
                Quantity = (int)detail.Attribute("quantity")
            }
        ).ToList()
     }
);