如何提取表达式的一部分

本文关键字:表达式 一部分 提取 何提取 | 更新日期: 2023-09-27 18:16:08

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

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表达式,除了在查询

如何提取表达式的一部分

我使用调试器查看可以从表达式中得到什么,发现提取所需内容相当简单。我猜它不漂亮,但它完成了工作。如果有人有什么建议,请发表评论。

    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;
    }