【问题标题】:List<T> LINQ Projection to Anonymous or Dynamic typeList<T> LINQ 投影到匿名或动态类型
【发布时间】:2012-02-26 06:08:47
【问题描述】:

我正在尝试通过 linq 投影将List&lt;Topic&gt; 转换为匿名或动态类型...我正在使用以下代码,但它似乎无法正常工作。它返回动态类型而没有错误,但是,如果我尝试枚举子字段 (list&lt;object/topic&gt;),那么它会说

结果视图 = 类型 '&lt;&gt;f__AnonymousType6&lt;id,title,children&gt;' 存在于“MyWebCore.dll”和“MvcExtensions.dll”中

奇怪。

这是我正在使用的代码:

protected dynamic FlattenTopics()
{
    Func<List<Topic>, object> _Flatten = null; // satisfy recursion re-use
    _Flatten = (topList) =>
    {
        if (topList == null) return null;

        var projection = from tops in topList
                         select new
                         {
                             id = tops.Id,
                             title = tops.Name,
                             children = _Flatten(childs.Children.ToList<Topic>())
                         };
        dynamic transformed = projection;
        return transformed;
    };

    var topics = from tops in Repository.Query<Topic>().ToList()
                 select new
                 {
                     id = tops.Id,
                     title = tops.Name,
                     children = _Flatten(tops.Children.ToList<Topic>())
                 };

    return topics;
}

我所做的只是展平一个自包含对象的列表 - 基本上它是一个 POCO 列表,将被填充到树视图 (jstree) 中。

Topic 类定义为:

public class Topic
{
    public Guid Id {get;set;}
    public string Name {get;set;}
    public List<Topic> Children {get;set;}
}

下面是返回的动态对象的第一个成员的示例:

[0] = { 
    id = {566697be-b336-42bc-9549-9feb0022f348},
    title = "AUTO", 
    children = {System.Linq.Enumerable.SelectManyIterator
          <MyWeb.Models.Topic,
           MyWeb.Models.Topic,
           <>f__AnonymousType6<System.Guid,string,object>
          >} 
 }

【问题讨论】:

  • 你是从另一个程序集中调用 FlattenTopics 吗?不能跨程序集使用匿名类型:stackoverflow.com/questions/2993200/…
  • LINQ 结果在范围之外不能很好地工作,因为匿名类型:msdn.microsoft.com/en-us/magazine/ee336312.aspx
  • @Igor - 否 - 来自我的 MVC 控制器中的 Action 方法...
  • @Ryan - 即使在主题 var 返回到调用 Action 方法之前,它也会给出上面帖子中解释的相同问题。 Children 子对象仅被填充到大约一两个级别。
  • @bbqchickenrobot 您递归调用的Action 是每次递归的新作用域。

标签: c# linq c#-4.0


【解决方案1】:

为什么你有两次相同的 LINQ 代码?定义 _Flatten 函数后,您可以立即调用它 - var topics = _Flatten(Repository.Query&lt;Topic&gt;().ToList()

看起来您正在创建两种相同的匿名类型,一种在 _Flatten 函数内部,一种在其外部。我认为编译器足够聪明来处理这个问题,但是尝试更改您的调用以显式使用 _Flatten,看看它是否解决了问题。

【讨论】:

    【解决方案2】:

    这是正确的方法 - 必须加载到 DTO / POCO 并返回:

    _Flatten = (topList) =>
            {
                if (topList == null) return null;
    
                var projection = from tops in topList
                                 //from childs in tops.Children
                                 select new JsTreeJsonNode
                                 {
                                     //id = tops.Id.ToString(),
                                     data = tops.Name,
                                     attr = setAttributes(tops.Id.ToString(), tops.URI),
                                     state = "closed",
                                     children = _Flatten(tops.Children)
                                 };
    
    
                return projection.ToList();
            };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-07
      • 1970-01-01
      • 1970-01-01
      • 2016-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多