protected override Expression VisitMemberInit(MemberInitExpression node) { ExpansionOptions expansion = expansions.First(); if (node.NewExpression.Type != expansion.ParentType) { return(base.VisitMemberInit(node)); } return(Expression.MemberInit ( Expression.New(node.Type), node.Bindings.OfType <MemberAssignment>().Aggregate ( new List <MemberBinding>(), AddBinding ) )); List <MemberBinding> AddBinding(List <MemberBinding> list, MemberAssignment binding) { if (ListTypesAreEquivalent(binding.Member.GetMemberType(), expansion.MemberType) && string.Compare(binding.Member.Name, expansion.MemberName, true) == 0) //found the expansion { if (foundExpansions.Count > 0) { throw new NotSupportedException("Recursive queries not supported"); } AddBindingExpression(GetBindingExpression(binding, expansion)); } else { list.Add(binding); } return(list); void AddBindingExpression(Expression bindingExpression) { list.Add(Expression.Bind(binding.Member, bindingExpression)); foundExpansions.Add(bindingExpression); } } }
protected override Expression GetBindingExpression(MemberAssignment binding, ExpansionOptions expansion) { if (expansion.QueryOption != null) { return(QueryFunctionAppender.AppendQueryMethod(binding.Expression, expansion, mapper)); } else if (expansions.Count > 1) //Mutually exclusive with expansion.QueryOption != null. { //There can be only one set of QueryOptions in the list. return(UpdaterExpansion ( binding.Expression, expansions.Skip(1).ToList(), mapper )); } else { throw new ArgumentException("Last expansion in the list must have a filter", nameof(expansions)); } }
public bool Equals(ExpansionOptions other) { return(Value == other.Value); }
public static Expression AppendQueryMethod(Expression expression, ExpansionOptions expansion, IMapper mapper) => new QueryFunctionAppender(expression, expansion, mapper).Visit(expression);
public QueryFunctionAppender(Expression expression, ExpansionOptions expansion, IMapper mapper) { this.expansion = expansion; this.expression = expression; this.mapper = mapper; }
private TREENODE ExpandTreeNode( TREENODE parentNode, TREENODE startNode, int row, int column, ObjectStyle branchStyle, bool insertNewChild, out ExpansionOptions expansionOptions, out int itemIncr, out bool requireInitialSubItemExpansion) { TREENODE tnCur; TREENODE tn1; TREENODE tn2; TREENODE newChildNode = null; // Don't test expandable while loading a complex column, the request can be ambiguous. // Just go ahead and fire off the request. A null return will leave the cell as a simple item. Debug.Assert( branchStyle == ObjectStyle.SubItemRootBranch || parentNode.Branch.IsExpandable(row, column), "GetExpandable should be called before this is attempted"); IBranch newBranch; try { SetStateFlag(TreeStateFlags.InExpansion, true); var options = 0; newBranch = parentNode.Branch.GetObject(row, column, branchStyle, ref options) as IBranch; expansionOptions = (ExpansionOptions)options; } finally { SetStateFlag(TreeStateFlags.InExpansion, false); } itemIncr = 0; requireInitialSubItemExpansion = false; newChildNode = null; if (newBranch != null) { itemIncr = newBranch.VisibleItemCount; //ExpansionCount can be 0 on success, don't check // UNDONE_MC: Only allow multi-column children if the parent branch does, // or if this is the root node of a complex item in the last column of a tree. var allowMultiColumn = true; tnCur = CreateTreeNode(startNode, newBranch, this, allowMultiColumn, parentNode.InSubItemColumn, parentNode.MultiColumn); tnCur.Index = row; tnCur.ImmedCount = tnCur.FullCount = itemIncr; if (allowMultiColumn && tnCur.MultiColumn && tnCur.ComplexColumns) { requireInitialSubItemExpansion = true; } tnCur.Expanded = true; tnCur.AllowRecursion = (expansionOptions & ExpansionOptions.BlockRecursion) == 0; tnCur.UpdateDelayed = false; tnCur.Parent = parentNode; if (tnCur.Dynamic) { AddTrackedNode(newBranch, tnCur); } newChildNode = tnCur; if (insertNewChild && startNode == null) { //Place node in proper position in child chain based on index tn1 = parentNode.FirstChild; tn2 = null; if (tn1 != null) { while (row >= tn1.Index) { Debug.Assert(tn1.Index != row, "TrackIndex screwed up"); tn2 = tn1; if (null == (tn1 = tn2.NextSibling)) { break; } } if (tn2 != null) { tn2.NextSibling = tnCur; } else { parentNode.FirstChild = tnCur; } tnCur.NextSibling = tn1; //tn1 May be null, not worth the check } else { parentNode.FirstChild = tnCur; } } } return newChildNode; }
private TREENODE ExpandTreeNode( TREENODE parentNode, TREENODE startNode, int row, int column, ObjectStyle branchStyle, bool insertNewChild, out ExpansionOptions expansionOptions, out int itemIncr, out int subItemIncr) { bool requireInitialSubItemExpansion; subItemIncr = 0; var retVal = ExpandTreeNode( parentNode, startNode, row, column, branchStyle, insertNewChild, out expansionOptions, out itemIncr, out requireInitialSubItemExpansion); if (retVal != null && requireInitialSubItemExpansion) { try { // UNDONE_MC: The full subitem gain will be higher than the immediate // gain if the expanded items are also complex ExpandInitialComplexSubItems(retVal as TREENODE_Multi, out subItemIncr); } catch (Exception ex) { Debug.Assert(false, ex.Message, ex.StackTrace); // Swallow this exception. The tree is left in a very bad state // if we get this far into an expansion and then throw. } finally { // These values may be positive already set if startnode is set, // so increment instead of blindly setting to subItemIncr. retVal.FullSubItemGain += subItemIncr; } } return retVal; }
public static Expression AppendFilter(Expression expression, ExpansionOptions expansion, IMapper mapper) => new FilterAppender(expression, expansion, mapper).Visit(expression);
public FilterAppender(Expression expression, ExpansionOptions expansion, IMapper mapper) { this.expansion = expansion; this.expression = expression; this.mapper = mapper; }
protected abstract Expression GetBindingExpression(MemberAssignment binding, ExpansionOptions expansion);