如何修改或插入表达式树的位置

时间:2013-08-22 09:21:14

标签: linq where expression-trees

默认我有这个:

Expression<Func<ItemGroup, ItemGroupView>> Exp = 
    m => new ItemGroupView{
        ID = m.id,
        Name = m.name,
        TotalCount = m.groupDetail.Sum(n => n.item.itemDetail.Count())
    };

但在运行时,我可能想添加多个过滤器。因此,例如,如果我将状态指定为1,将类别指定为矿物,那么它将变为

Expression<Func<ItemGroup, ItemGroupView>> Exp = 
    m => new ItemGroupView{
        ID = m.id,
        Name = m.name,
        TotalCount = m.groupDetail.Sum(
            n => n.item.itemDetail
            .Where(o => o.status == 1 && o.category == "mineral")
            .Count())
    };

// ItemGroup.groupDetail is collection of ItemGroupDetail (n)
// ItemGroupDetail.item is Item
// Item.itemDetail is collection of ItemDetail  (o)
// ItemDetail.item is Item

如何修改表达式树以动态插入多个Where

到目前为止,我做了像这样的默认

private int _status;
private string _category;

internal Expression<Func<ItemDetail, bool>> whereStatus()
{
    return o => o.status == _status;
}

internal Expression<Func<ItemDetail, bool>> whereCategory()
{
    return o => o.category == _category ;
}

internal Expression<Func<ItemGroup, ItemGroupView>> GetEx()
{
    return m => new ItemGroupView{
        ID = m.id,
        Name = m.name,
        TotalCount = m.groupDetail.Sum(n => n.item.itemDetail.Count())
    };
}

internal IQueryable<ItemGroupView> GetSelectQuery(IQueryabe<ItemGroup> ie)
{
    ParameterExpression m = Expression.Parameter(typeof(ItemGroup), "m");
    ParameterExpression n = Expression.Parameter(typeof(ItemGroupDetail), "n");

    MemberInitExpression ex = (MemberInitExpression)GetEx().Body;

   // ParameterReplacer is inherited from ExpressionVisitor
    ex = (MemberInitExpression)new ParameterReplacer(
        new ParameterExpression[] { m, n }).Visit(ex);

    // ? ? ? ?  
    // how to modify the Expression if _status or _category is supplied?

    Expression<Func<ItemGroup, ItemGroupView>> el =
        Expression.Lambda<Func<ItemGroup, ItemGroupView>>
                    (ex, new ParameterExpression { m });

    return ie.Select(el);
}

编辑: ItemGroup.itemDetail更改为ItemGroup.groupDetail,以避免组和项之间的混淆..

1 个答案:

答案 0 :(得分:0)

如果您可以创建表示Where()操作的表达式,则可以使用LINQKit将其粘贴到主表达式中:

Expression<Func<IQueryable<ItemDetail>, IQueryable<ItemDetail>>> whereExpression=
    id => id.Where(o => o.status == 1 && o.category == "mineral");

Expression<Func<ItemGroup, ItemGroupView>> Exp =
    m => new ItemGroupView
    {
        ID = m.id,
        Name = m.name,
        TotalCount =
            whereExpression.Invoke(m.itemDetail)
                .Sum(n => n.item.itemDetail.Count())
    };
Exp = Exp.Expand();

(不要忘记最后一行,这很重要。)