如何使用嵌套对象转换对象

时间:2009-12-10 11:02:00

标签: c# entity-framework hierarchy

我有一个实体,它实际上是树对象结构(仅定义我实体中的相关属性):

public class TreeItem
{

    public int Id { get; set; }

    public TreeItem Parent { get; set; }

    public List<TreeItem> Children { get; set; }

    ...

}

父级和子级属性已正确定义为导航属性。所以,当我打电话时:

var items = (from ti in context.TreeItem()
            select ti).ToList<TreeItem>();

我实际上是将我的物品放在树状结构中,因为EF在幕后工作,并在父母和孩子身上填充这些物品。

我现在要做的是将这些对象转换为非常多POCO的ViewModel对象。没有功能,只有数据。

我可以通过一个可以创建和填充新对象的递归方法来转换它们,但是有一种更简单的(就LoC而言 - 代码行)方式来进行这种转换吗?

1 个答案:

答案 0 :(得分:1)

this相关问题中,讨论了几种方法:

  • 递归的,可能是最容易实现的,但是就深度和项目数量的缩放而言,它是有限的,因为它倾向于指数级地花费更长时间并且存在溢出堆栈的风险
  • 另一种方法是使用在缩放方面具有更多线性增长的堆栈

请务必查看页面底部的Eric Lippert的评论。

更新,让您了解我的意思:

public static class Extensions
{
    public static IList<R> TransformTree<T, R>(this IEnumerable<T> collection,
        Func<T, IEnumerable<T>> entitySelector,
        Func<R, IList<R>> pocoSelector,
        Func<T, R> transformer)
    {
        var transformedList = new List<R>();
        var stack = new Stack<IEnumerable<T>>();
        var parents = new Dictionary<IEnumerable<T>, R>();

        stack.Push(collection);

        while (stack.Count > 0)
        {
            IEnumerable<T> items = stack.Pop();

            R transformedParent;

            IList<R> parentChildren = parents.TryGetValue(items, out transformedParent)
                                          ? pocoSelector(transformedParent)
                                          : transformedList;

            foreach (var item in items)
            {
                R transformedItem = transformer(item);
                parentChildren.Add(transformedItem);

                IEnumerable<T> children = entitySelector(item);

                stack.Push(children);
                parents.Add(children, transformedItem);
            }
        }

        return transformedList;
    }
}

这样称呼:

treeItems.TransformTree<TreeItem, TreeItemPoco>(
  (item) => { return item.Children; },
  (pocoItem) => { return pocoItem.Children; },
  (item) => { return new TreeItemPoco(item); });