Beispiel #1
0
        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));
        }
Beispiel #2
0
        // 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);
        }