如何提取表达式的一部分

时间:2013-05-30 11:02:01

标签: c# linq linq-to-sql lambda expression

我想简化代码以添加loadoptions和关联过滤,所以我创建了这个类。

class GraphQuery<T>
{
    private IQueryable<T> query;
    private DataLoadOptions load;

    public GraphQuery(DataLoadOptions load, IQueryable<T> query)
    {
        this.load = load;
        this.query = query;
    }

    public GraphQuery<T> Load(
            Expression<Func<T, object>> expr, 
            Expression<Func<T, object>> filter)
    {
        load.LoadWith(expr);
        load.AssociateWith(filter);
        return this;
    }

    // more public methods ...
}

然后可以像这样使用:

var clients = Graph(db.Clients.Where(e => !e.Deleted))
    .Load(e => e.ClientPersons, 
        e => e.ClientPersons.Where(j => !j.Person.Deleted));

但是,我看到e => e.ClientPersons的重复非常简单。所以我想将上述用法减少到:

var clients = Graph(db.Clients.Where(e => !e.Deleted))
    .Load(e => e.ClientPersons.Where(j => !j.Person.Deleted));

所以Load函数看起来应该像

    public GraphQuery<T> Load(Expression<Func<T, object>> filter)
    {
        var expr = ... extract first part of the expression that represents the association property
        load.LoadWith(expr);
        load.AssociateWith(filter);
        return this;
    }

我从未使用linq表达式,除了在查询中使用它们

1 个答案:

答案 0 :(得分:0)

我使用调试器来查看从表达式中可以获得的内容,并发现提取我需要的内容相当简单。我猜它不漂亮,但它完成了工作。如果有人提出改进建议 - 请发表评论。

    private static LambdaExpression GetRootMemberExpression(LambdaExpression lambda1)
    {
        var expr = lambda1.Body;
        while (!FindRoot(ref expr)) ;
        if (!(expr is MemberExpression))
            throw new Exception("MemberExpression required");
        return Expression.Lambda(expr, (expr as MemberExpression).Expression as ParameterExpression);
    }


    private static bool FindRoot(ref Expression expr)
    {
        if (expr is MemberExpression)
            return FindRoot(ref expr, (expr as MemberExpression).Expression);
        if (expr.NodeType == ExpressionType.Call)
            return FindRoot(ref expr, (expr as MethodCallExpression).Object);
        throw new Exception("Unexpected Expression type encountered (" + expr.NodeType + ")");
    }

    private static bool FindRoot(ref Expression expr, Expression expr2)
    {
        if (expr2.NodeType == ExpressionType.Parameter)
            return true;
        expr = expr2;
        return false;
    }