protected override Expression Transform(CallExpression lx) { if (!Operators.WildcardComparators.Contains(lx.OperatorName) || lx.Operands.Length != 2) { return(base.Transform(lx)); } var lhsIs = WildcardSearch.FindElementAtWildcard(lx.Operands[0]); var rhsIs = WildcardSearch.FindElementAtWildcard(lx.Operands[1]); if (lhsIs != null && rhsIs != null || lhsIs == null && rhsIs == null) { return(base.Transform(lx)); // N/A, or invalid } var wildcardPath = lhsIs != null ? lx.Operands[0] : lx.Operands[1]; var comparand = lhsIs != null ? lx.Operands[1] : lx.Operands[0]; var indexer = lhsIs ?? rhsIs !; var px = new ParameterExpression("p" + _nextParameter++); var nestedComparand = NodeReplacer.Replace(wildcardPath, indexer, px); var coll = indexer.Receiver; var wc = ((IndexerWildcardExpression)indexer.Index).Wildcard; var comparisonArgs = lhsIs != null ? new[] { nestedComparand, comparand } : new[] { comparand, nestedComparand }; var body = new CallExpression(lx.IgnoreCase, lx.OperatorName, comparisonArgs); var lambda = new LambdaExpression(new[] { px }, body); var op = Operators.ToRuntimeWildcardOperator(wc); var call = new CallExpression(false, op, coll, lambda); return(Transform(call)); }
// Reduces the size of a supplied expression tree by compiling parts of the tree into individual // delegates. Besides preventing the CLR from throwing stack overflow exceptions (which will happen // when the tree gets somewhere between 20,000 and 50,000 nodes), this can reduce the amount of code // that needs to be JITted and can therefore reduce the memory footprint of the application. private static Expression ReduceObjectGraphSize(Expression expression, Container container, Dictionary <Expression, InvocationExpression> reducedNodes = null) { var results = NodeSizeCalculator.Calculate(expression); while (results.TotalSize > container.Options.MaximumNumberOfNodesPerDelegate) { reducedNodes = reducedNodes ?? new Dictionary <Expression, InvocationExpression>(16); Expression mostReductiveNode = FindMostReductiveNodeOrNull(results, container.Options.MaximumNumberOfNodesPerDelegate); if (mostReductiveNode == null) { // In case mostReductiveNode is null, there's no good candidate to reduce the object // graph. In that case we break out. break; } // If the found mostReductiveNode has been reduced before, we use the previously compiled // value (instead of doing the compilation all over again). Otherwise we compile that node. InvocationExpression replacementNode = reducedNodes.ContainsKey(mostReductiveNode) ? reducedNodes[mostReductiveNode] : CompileToInvocation(mostReductiveNode, container, reducedNodes); reducedNodes[mostReductiveNode] = replacementNode; expression = NodeReplacer.Replace(expression, oldNode: mostReductiveNode, newNode: replacementNode); results = NodeSizeCalculator.Calculate(expression); } return(expression); }