/// <summary> /// Returns the member expressions in the expression hierarchy of the <paramref name="expression"/> /// </summary> /// <param name="expression">The expression to search</param> /// <returns>A collection of <see cref="MemberExpression"/> objects</returns> internal static IEnumerable <MemberExpression> GetMemberExpressions(this Expression expression) { List <MemberExpression> members = new(); VisitorHelper.VisitMembers(expression, (expr, recurse) => { members.Add(expr); return(recurse(expr)); }); return(members); }
/// <summary> /// Walk the expression and compute all the subtrees that are not dependent on any /// of the expressions parameters. /// </summary> /// <param name="expression">The expression to analyze.</param> /// <returns>A collection of all the expression subtrees that are independent from the expression parameters.</returns> internal static List <Expression> FindIndependentSubtrees(this Expression expression) { List <Expression> subtrees = new(); // The dependenty and isMemberInit flags are used to communicate between different layers // of the recursive visitor. bool dependent = false; bool isMemberInit = false; // Walk the tree, finding the independent subtrees VisitorHelper.VisitAll(expression, (expr, recurse) => { if (expr != null) { bool parentIsDependent = dependent; bool parentIsMemberInit = isMemberInit; // Set flags dependent = false; isMemberInit = expr is MemberInitExpression; // Recurse recurse(expr); // If nothing in my subtree is dependent if (!dependent) { // A NewExpression itself will appear to be indepentt, but if the parent is a MemberInitExpression, // then the NewExpression can't be evaluated by itself. The MemberInitExpression will determine // if the full expression is dependent or not, so don't check it here. if (expr is NewExpression newExpression && parentIsMemberInit) { return(expr); } // The current node is independent if it's not related to the parameter and it's not the constant query root. ConstantExpression constant = expr as ConstantExpression; if (expr.NodeType == ExpressionType.Parameter || (constant?.Value is IQueryable)) { dependent = true; } else { subtrees.Add(expr); } }